So this is something I guess many people want to do, mock a collection. In the past with Rhino I have done this with something like:
var col_mock = MockRepository.GenerateMock<ICustomCollection>(); // returns ICustom let's say
List<ICustom> col_real = new List<ICustom>();
col_real.Add(custom_mock1);
col_real.Add(custom_mock2);
col_real.Add(custom_mock3);
col_mock.Stub(x => x.GetEnumerator()).Return(col_real.GetEnumerator());
So yup this works fine, when you foreach col_mock you get the mocked (custom_mock1 etc.) objects back. Great! We have successfully mocked a custom collection by using a typed list to actually store a load of mocked objects.
The problem is, you can only do this once! you can only foreach this collection once. Does anyone know (without creating an actual custom collection...) how I can achieve the mocking of a custom collection which can be iterated more than once?
Actually, no. The point of a mock is to quickly conjure up an object with a specific interface and behavior that you have full control over, so that you can exercise your class under test.
But in the case where you need an
ICollection<Foo>
, you can typically just create aList<Foo>
instance. You can populate a list in your unit test any way you want; you already have full control.Or suppose you need a
IEnumerable<Foo>
with more interesting behavior that you can't produce with a list, like an infinite enumerable or an enumerable that throws exceptions. This can be done by defining an iterator method in your unit test class with theyield
keyword. Again, a mock is not necessary.The problem is that the enumerator is only instantiated once, when you call
Return
. Then it returns the same instance which is already at the end of the list after the firstforeach
.You need to instantiate a new enumerator each time when
GetEnumerator
is called. You could useWhenCalled
to do so.Return
is still needed, because Rhino Mocks will complain when it is missing. But it doesn't matter what you pass as argument.