NSubstitute
NSubstitute copied to clipboard
Exception thrown when mocking IRequestCookieCollection
This is unusual and I have no idea what's going on.
When attempting to mock TryGetValue
in httpContext.Request.Cookies
:
[TestMethod]
public void Test()
{
var httpContext = new DefaultHttpContext();
httpContext.Request.Cookies = Substitute.For<IRequestCookieCollection>();
httpContext.Request.Cookies.TryGetValue("hello", out Arg.Any<string?>()).Returns(x =>
{
x[1] = "world!";
return true;
});
}
The code will give the following exception:
NSubstitute.Exceptions.UnexpectedArgumentMatcherException: 'Argument matchers (Arg.Is, Arg.Any) should only be used in place of member arguments. Do not use in a Returns() statement or anywhere else outside of a member call.
Correct use:
sub.MyMethod(Arg.Any<string>()).Returns("hi")
Incorrect use:
sub.MyMethod("hi").Returns(Arg.Any<string>())'
Any idea if I'm doing something wrong or is this possibly a bug?
Environment:
- NSubstitute version: 4.2.2
- NSubstitute.Analyzers version: 1.0.14
- Platform: netcoreapp3.1 (asp.net core) on Windows
Hi @koliva8245 ,
Thanks for the good repro steps! 👍
This does seem odd. This works as expected:
var cookies = Substitute.For<IRequestCookieCollection>();
cookies.TryGetValue("hello", out Arg.Any<string>()).Returns(x => {
x[1] = "world!";
return true;
});
This test fails:
var httpContext = new DefaultHttpContext();
var c = Substitute.For<IRequestCookieCollection>();
httpContext.Request.Cookies = c;
Assert.Same(c, httpContext.Request.Cookies);
/* FAIL:
Assert.Same() Failure
Expected: ObjectProxy []
Actual: RequestCookieCollection []
*/
So the assignment to Cookies
does not seem to be working? 🤯
var httpContext = new DefaultHttpContext();
var cookies = Substitute.For<IRequestCookieCollection>();
cookies.TryGetValue("hello", out Arg.Any<string?>()).Returns(x =>
{
x[1] = "world!";
return true;
});
var result = cookies.TryGetValue("hello", out var value);
Assert.AreEqual("world!", value); // passes
httpContext.Request.Cookies = cookies;
httpContext.Request.Cookies.TryGetValue("hello", out var httpValue);
Assert.AreEqual("world!", httpValue); // fails
Yeah, the assignment to httpContext.Request.Cookies
isn't working as it should. So it looks like I can't write test code for methods that use cookies. 😢
Any workarounds?
Is it possible to use the real cookie collection itself? That would be ideal for this case I think.
Otherwise you could look for mockable Http abstractions or check the source (here?) as to why the assignment is acting strangely.
Unfortunately the only implementation of IRequestCookieCollection
is RequestCookieCollection
which has been set as internal.
It seems that the httpContext.Request.Cookies
value cannot be changed, since even setting is as null
doesn't even work.
So I said heck with it and just mocked HttpContext
instead.
var httpContext = Substitute.For<HttpContext>();
httpContext.Request.Cookies.TryGetValue("hello", out Arg.Any<string?>()).Returns(x =>
{
x[1] = "world!";
return true;
});
httpContext.Request.Cookies.TryGetValue("hello", out string? value);
Assert.AreEqual("world!", value);
I assume your question has been answered, if not, please let us know!