giraffe.guru
giraffe.guru

Reputation: 500

Can I use Moq's SetupSequence to throw exception then return void?

I am trying to set up Moq to throw an exception on the first invocation and then return void on the second invocation. The method I'm mocking has a void return type (e.g. public void Bar()).

Things I have tried

This has compile errors because Returns requires an argument and SetupSequence requires type arguments.

_mock.SetupSequence(m => m.Bar())
    .Throws<Exception>()
    .Returns();

This has a compile error because Void is not a type in C#.

_mock.SetupSequence<IMyMock, Void>(m => m.Bar())
    .Throws<Exception>() // first invocation throws exception
    .CallBase();

Workaround

In the end I gave up on SetupSequence() and switched to Callback() to throw an exception.

var firstTime = true;
_mock.Setup(m => m.Bar())
    .Callback(() =>
    {
        if (firstTime)
        {
            firstTime = false;
            throw new Exception();
        }
    });

Question

SetupSequence takes a Func, not an Action. Am I correct in assuming that this means SetupSequence() cannot be used to mock void methods?

Upvotes: 3

Views: 3726

Answers (1)

You can do this starting with Moq 4.8.0:

SetupSequence support for void methods was discussed in GitHub issue #451 and added with GitHub pull request #463.

You're probably looking for the new .Pass() method:

mock.SetupSequence(m => m.VoidMethod())
    .Throws(new InvalidOperationException())
    .Pass()
    .Pass()
    .Throws(new InvalidOperationException())
    .Pass();

Note that trailing calls to .Pass() are probably unnecessary.

Upvotes: 11

Related Questions