Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
voroninp opened this issue Mar 14, 2020 · 5 comments
Labels

Comments

@voroninp
Copy link

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.

@voroninp
Copy link
Author

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.

@stakx
Copy link
Contributor

stakx commented Mar 14, 2020

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().

@voroninp
Copy link
Author

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

@kzu kzu transferred this issue from moq/labs Oct 29, 2020
@kzu
Copy link
Member

kzu commented Oct 29, 2020

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

Thanks

@stakx
Copy link
Contributor

stakx commented Oct 29, 2020

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.

@stakx stakx closed this as completed Oct 29, 2020
@stakx stakx added the question label Oct 29, 2020
@devlooped devlooped locked and limited conversation to collaborators Sep 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants