1

Unexpected behaviour from RhinoMocks:

var mocks = new MockRepository();
var connection = mocks.Stub<OracleConnection>();
var command = mocks.Stub<OracleCommand>();

using (mocks.Record()) {
    connection.Expect(x => x.CreateCommand()).Return(command);
    command.Expect(x => x.ExecuteNonQuery());
    command.Expect(x => x.Dispose());
}

using (mocks.Playback()) {
    using(var command = connection.CreateCommand()) {
        ...
        command.ExecuteNonQuery();
    }
}

Allthough I have expected the Dispose()-Call, it is not recognized and I am getting the following message:

Rhino.Mocks.Exceptions.ExpectationViolationException: IDisposable.Dispose(); Expected #0, Actual #1.

If I rewirte the code without the using-clause everything is fine:

OracleCommand cmd = null;
try {
    command = connection.CreateCommand();
    ...
    command.ExecuteNonQuery();
}
finally {
    if (command != null)
        command.Dispose();
}

Any ideas on this issue?

Regards, MacX

Jay
  • 56,361
  • 10
  • 99
  • 123
MacX
  • 587
  • 5
  • 16

1 Answers1

2

This question and answer suggest that the problem may stem from the fact that you are stubbing out OracleCommand, rather than an IDbCommand or similar.

The comments on the accepted answer suggest that if OracleCommand is an abstract class, you should be mocking it using GeneratePartialMock<OracleCommand>().

I hope this helps you.

edit

In response to your comment, it sounds like you need the implementation-specific methods of OracleCommand, but can't mock it properly.

Although OracleCommand is sealed, you could wrap it compositionally. It takes some legwork, but will allow you to both use OracleCommand in your code and mock it in your tests.

public interface IOracleCommand : IDbCommand
{
    void OracleMethod();
    string OracleProperty { get; set; }
}

public class OracleCommandWrapper : IOracleCommand
{
    private OracleCommand _inner;

    public OracleCommandWrapper(OracleCommand inner)
    {
        _inner = inner;
    }

    public void Dispose()
    {
        _inner.Dispose();
    }

    public IDbDataParameter CreateParameter()
    {
        return _inner.CreateParameter();
    }

    // do this for all the members, including the Oracle-specific members

    public void OracleMethod()
    {
        _inner.OracleMethod();
    }

    public string OracleProperty
    {
        get { return _inner.OracleProperty; }
        set { _inner.OracleProperty = value; }
    }
}

Now you can use IOracleCommand and OracleCommandWrapper in your code, and in your tests you just mock or stub off of the IOracleCommand interface.

Again, it takes some legwork, but gets you where you want to be.

Community
  • 1
  • 1
Jay
  • 56,361
  • 10
  • 99
  • 123
  • Due to the fact that OracleConnection-Class and others are sealed, I get a 'System.NotSupportedException: Can't create mocks of sealed classes.'-Message while creating the mock. So this is not an opportunity. Otherwise A testing directly to the database is not really what I want – MacX May 24 '11 at 14:52
  • @MacX - OracleConnection derives from DbConnection, which implements IDbConnection. This is the interface you want to mock and inject, instead of creating an instance/mock/stub/etc. of OracleConnection. – Pedro May 24 '11 at 21:26
  • This would be an opportunity, in general. But in fact, I need some special features provided by Oracle's implementation for example the arraybinding for large inserts - [Oracle's ArrayBinding](http://dotnetslackers.com/articles/ado_net/BulkOperationsUsingOracleDataProviderForNETODPNET.aspx) – MacX May 25 '11 at 06:02
  • thats quite an overhead for my needs i think. while this problem doen't make me more do than rewrite the using-clauses, I would prefer the rewrite than wrapping Oracle, but many thanks anyway – MacX May 26 '11 at 13:45