I created an extension method for calling moq in order (see below) per this SO answer.
An example use case is:
mock.setup.CallbackSequence(new List{h,e,l,l,o})
where I pass hello
into my SUT
and expect the characters in order.
The problem is this case:
mock.setup.CallbackSequence(new List{h,e,l,l,o,X})
where I pass hello
. This will pass even though it should fail because of the dynamic assertion nature (X is never sent in, but we never know). The only way I can think of to fix this would be to add a
mock.Verify(setupmethod, Times.Exactly(list.Count))
However, the callback setup and the verify are done in two different places, so it would fall on the consumer of the extension method to realize this flaw. I would like to avoid putting that on them, as it is bound to fail.....suggestions?
public static ICallbackResult CallbackSequence<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList) where TMockType : class
{
//Refactor: Does not fail if it does not reach the end, only if out of order and/or too long
var index = 0;
return mockSetup.Callback((T1 t1, T2 t2) =>
{
if(index >= sequencedList.Count)
Assert.That(false, "Sequenced list attempted to access index out of bounds. Count is " + sequencedList.Count + "; index is " + index + "; value being checked is " + t1);
var currentItemInSequence = sequencedList[index];
Assert.That(t1, Is.EqualTo(currentItemInSequence), String.Format("Failed sequence at position{0}", index));
index++;
});
}
EDIT
The only thing I can think of that might work is to return a custom object that the consumer is supposed to call at the end:
var sequenceVerifier = ...CallbackSequence();
//Do Stuff
sequenceVerifier.VerifySequence();
This is still not optimal to me as this gives the impression that this will not verify until the VerifySequence is called, but it will only perform the edge case....unless I don't assert in the callback, but just track and assert at the end??????? That might work, thoughts????