Moq Triqs - Successive Expectations
I've posted this to the Moq discussion forum but I think it warrants its own post here too.
One of the (very minor) limitations we struck with Moq if that if you expect to call the same method more than once and get a different result each time, there's no straight forward way to set that up. If you try this:
mockCommand.Expect(c => c.CreateParameter()).Returns(mockParam1.Object); mockCommand.Expect(c => c.CreateParameter()).Returns(mockParam2.Object);
... then when your code calls CreateParameter() it'll just get the "mockParam2" object back twice, because the second expectation has "overwritten" the first.
We stumbled upon a nice workaround for this particular problem using an overload of IExpect.Returns which takes an expression rather than a value. Basically, every time the expected method is called, the expression is evaluated and its result is returned. So we use an expression to return a series of values, one after the other. Even nicer, we do so using the generic Queue object. Here's the code:
var pq = new Queue<IDbDataParameter>(new[] { mockParam1.Object, mockParam2.Object }); mockCommand.Expect(c => c.CreateParameter()).Returns(() => pq.Dequeue());
See what's happening? We "queue up" two parameters, and then "dequeue" them as the CreateParameter is called each time.
I know that the Moq guys are considering some sort of "sequence" feature to overcome the "successive expectations overwrite the previous ones" problem, but this queuing method works a treat for us.
# Trackback from Tim Van Wassenhove » Archive » Setup expectation with successive function calls using Moq on 14/03/2009 11:45 PM
# Trackback from Successive Method Calls With MoQ on 30/09/2009 1:30 PM
Comments
# NJoco
13/03/2009 1:09 AM
Exactly what I find :)
Thanks!
# nick
24/07/2009 12:55 AM
brilliant idea, just what I needed...
# Page Brooks
1/10/2009 2:51 AM
This rocks! Much better than the technique I was using.
# Darren
17/07/2010 3:15 AM
Thanks, I knew something like this existed just didn't know an easy way to implement it.
# Igor Zevaka (@izevaka)
1/09/2010 10:41 AM
Great, works a treat, thanks for that.
# Mark G
20/10/2010 7:45 PM
Great solutions. Simple, elegant and effective.
# Steve R
25/04/2011 6:47 PM
Fantastic, just what I needed! Works just as well with the mock.Setup(...) syntax.
# Gene
29/07/2011 3:45 AM
Not sure why you would consider this to be a minor issue. Is it because there is an easy workaround or because he should be rare that the same method is called multiple times? If it is the later then we have code smells all over our code because we call the same method multiple times in many places.
# Jordan
27/10/2011 6:38 AM
This helped me out a lot, till I got to how to do outs. Thought I'd drop my solution back to ya.
var foo = new Mock<IFoo>();
string output;
var outputs = new Queue<string>(new[] {"OneFish", "TwoFish", "RedGoat", "BlueFish"});
foo.Setup(r => r.TryParseToFish(out output))
.Returns(new Queue<bool>(new[] { true, true, false, true}).Dequeue);
.Callback(() => output = outputs.Dequeue());
# Scott M.
3/02/2013 3:31 AM
Using NUnit, you could simply set up a test method that takes a [Values n, n, n] parameter and then just have the test have the expect line just once (specifying the test method parameter for the expect parameter. The test will run once for each parameter supplied to the [Values] attribute.