开发者

RhinoMocks Unexpected Dispose()

开发者 https://www.devze.com 2023-03-08 05:39 出处:网络
Unexpected behaviour from RhinoMocks: var mocks = new MockRepository(); var connection = mocks.Stub<OracleConnection>();

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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消