Moq4: [Bug?] MockException: invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.

Created on 14 Mar 2020  路  5Comments  路  Source: moq/moq4

Steps to Reproduce

For this code and Strict mode I get :

MockException: SendAsync(null, CancellationToken) invocation failed with mock behavior Strict.
All invocations on the mock must have a corresponding setup.

For Loose mode result is null, and not an instance of HttpResponseMessage.

But should it be like that if I defined behaviour for public abstract method?!

void Main()
{
    var method = typeof(TestHandler).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Single(m => m.Name == "SendAsync");

    var mock = new Mock<TestHandler>(MockBehavior.Strict);
    mock.Setup(x => x.MockableSendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>())).ReturnsAsync(new HttpResponseMessage());

    var result = method.Invoke(mock.Object, new object[] { null, CancellationToken.None}) as Task<HttpResponseMessage>;
    result.Wait();
}

public abstract class TestHandler : HttpMessageHandler
{
    public abstract Task<HttpResponseMessage> MockableSendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return this.MockableSendAsync(request, cancellationToken);
    }
}

Expected Behavior

I expect that protected overridden method works as it is.

question

Most helpful comment

Still not decided on how protected setups would work on v5. You can follow https://github.com/moq/moq/issues/51.

Thanks

All 5 comments

Moreover, whenever I make it

protected sealed override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

Moq is happy, and everything works. The only problem is that in reality class is defined in F#, and F# does not support sealed methods.

Disclaimer: The following info is valid for Moq 4.x (which lives at https://github.com/moq/moq4), it may not be accurate for Moq 5.x (this repository).

This is expected behavior. Strict mode means that you must provide a setup for all methods you are calling. The methods' accessibility (public vs. protected) doesn't matter. What does matter is that rule holds only for methods that are interceptable by Moq; this excludes sealed, non-virtual, and static methods.

So (a) use either a loose mock together with CallBase = true, or (b) add a setup for your protected SendAsync method: mock.Protected().Setup("SendAsync", ...).CallBase().

Thanks, now it is clear. What are the changes for Moq 5.x?

Still not decided on how protected setups would work on v5. You can follow https://github.com/moq/moq/issues/51.

Thanks

I am going to close this issue since it is now in this repo, and an answer for Moq v4 has already been given above.

Was this page helpful?
0 / 5 - 0 ratings