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.
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.