Rhino mocks AssertWasCalled does not work

263 Views Asked by At

I wrote the following test case to illustrate my problem using Rhino Mocks:

[TestClass]
public class Tester
{
    public class TestList<T> : List<T>
    {
        public override bool Equals(object obj)
        {
            // obj is an empty list here??
            return base.Equals(obj);
        }
    }

    public interface IStubbedInterface
    {
        void DoSomethingWithList(TestList<int> list);
    }

    public class ClassToTest
    {
        public IStubbedInterface TheStub { get; set; }

        public void Run()
        {
            var list = new TestList<int> { 1, 2 };
            TheStub.DoSomethingWithList(list);
            list.Clear();
        }
    }

    public bool Match(TestList<int> arg)
    {
        // Here arg is an empty list??
        return arg == new TestList<int> { 1, 2 };
    }

    [TestMethod]
    public void Test()
    {
        var classToTest = new ClassToTest();
        classToTest.TheStub = MockRepository.GenerateMock<IStubbedInterface>();
        classToTest.Run();
        classToTest.TheStub.AssertWasCalled(
            x => x.DoSomethingWithList(new TestList<int>() { 1, 2 }));
            //x => x.DoSomethingWithList(Arg<TestList<int>>.Matches(arg => Match(arg))));
    }
}

The test case will fail on the AssertWasCalled() line, no matter if I compare the list directly or using the Arg<>.Matches(..) syntax. I also tried with MockRepository.GenerateStub<>(..) instead of GenerateMock<>(..), which also fails. It fails because of the list.Clear(); line after calling DoSomethingWithList(), which results in the list also being empty at the time of AssertWasCalled(). Is this a bug with RhinoMocks? I would have assumed that RhinoMocks would record a snapshot of the argument somehow when the asserted function was called, but it looks like RhinoMocks keeps using the same object?

In the real case where I encountered this problem the argument of the function I was testing was wrapped in a using() statement, which lead to the same effect of AssertWasCalled not being able to test the arguments passed.

1

There are 1 best solutions below

0
On

Looks like using the Expect()/VerifyAllExpectations() pattern works better for this test scenario. Changing the test case to the below code will pass.

This is rather unfortunate as I much prefer using AssertWasCalled(), however as it stands it is rather unreliable.

[TestMethod]
public void Test()
{
    var classToTest = new ClassToTest();
    classToTest.TheStub = MockRepository.GenerateMock<IStubbedInterface>();
    classToTest.TheStub.Expect(
        x => x.DoSomethingWithList(new TestList<int>() { 1, 2 }));
    classToTest.Run();
    classToTest.TheStub.VerifyAllExpectations();
}