What's the most succinct way to use Moq to mock a method that will throw an exception the first time it is called, then succeed the second time it is called?
Asked
Active
Viewed 2.2k times
4 Answers
69
I would make use of Callback
and increment a counter to determine whether or not to throw an exception from Callback
.
[Test]
public void TestMe()
{
var count = 0;
var mock = new Mock<IMyClass>();
mock.Setup(a => a.MyMethod()).Callback(() =>
{
count++;
if(count == 1)
throw new ApplicationException();
});
Assert.Throws(typeof(ApplicationException), () => mock.Object.MyMethod());
Assert.DoesNotThrow(() => mock.Object.MyMethod());
}
public interface IMyClass
{
void MyMethod();
}

rsbarro
- 27,021
- 9
- 71
- 75
-
this is a good answer and this approach becomes preferable once you want more than 2 things to happen. – anthony Aug 12 '11 at 20:50
-
This approach is simple which is nice, but check that post by Phil Haack from @Mathias' answer. It's pretty slick. Using an extension method you can do something like `reader.Setup(r => r.Read()).ReturnsInOrder(true, true, false);` – rsbarro Aug 12 '11 at 20:52
-
5ReturnsInOrder() is nice if you want to return a sequence of values but it wasn't readily apparent how to use it to throw an exception as part of the sequence. – anthony Aug 12 '11 at 20:56
-
3This answer is not wrong, but using `SetupSequence` is easier and more elegant for sure. Check @aghidini's answer. – Martijn Oct 07 '21 at 13:21
65
Starting with Moq 4.2 you can just use the built-in method SetupSequence()
(as stated by @RichardBarnett comment).
Example:
var mock = new Mock<IMyClass>();
mock.SetupSequence(x => x.MyMethod("param1"))
.Throws<MyException>()
.Returns("test return");

aghidini
- 2,855
- 5
- 29
- 32
-
5This only works if `MyMethod` has a return type. If the method is `void` then you can't use this approach. Would be nice if there were a way to do this with `void` methods – Simon Jan 29 '20 at 10:58
18
The best that I've come up with so far is this:
interface IFoo
{
void Bar();
}
[Test]
public void TestBarExceptionThenSuccess()
{
var repository = new MockRepository(MockBehavior.Default);
var mock = repository.Create<IFoo>();
mock.Setup(m => m.Bar()).
Callback(() => mock.Setup(m => m.Bar())). // Setup() replaces the initial one
Throws<Exception>(); // throw an exception the first time
...
}

anthony
- 40,424
- 5
- 55
- 128
-
2+1 That's a cool approach. Just might not be clear to someone stumbling into the code what's going on there. – rsbarro Aug 12 '11 at 20:00
-
-
5Note that replacing the mock wipes out the history so you can't do `mock.Verify(m => m.Bar(), Times.Exactly(2))`. – giraffe.guru Dec 10 '17 at 21:10
7
Phil Haack has an interesting blog post on setting up a method to return a particular sequence of results. It seems that it would be a good starting point, with some work involved, because instead of a sequence of values of a certain type, you would need now to have a sequence of results which could be of type T, or an exception.

Mathias
- 15,191
- 9
- 60
- 92