8

I'm getting the following error:

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()).Returns("hi") Incorrect use:
sub.MyMethod("hi").Returns(Arg.Any())'

When trying to mock out the following interface:

public interface IMyDate
{
    DateTime GetDate();
}

Here's where I mock it:

var myDate = Substitute.For<IMyDate>();
myDate.GetDate().Returns(testDate); // Error thrown here

Please can anyone explain what I'm doing wrong?

var myDate = Substitute.For<IMyDate>();
myDate.GetDate().Returns(new DateTime(2018, 04, 05)); // Error thrown here

Gives the same result.

5 Answers5

5

This might be due to a problem with an earlier test. See this answer for some steps for tracking down this issue. I've included a snapshot of that answer below:

This is most like due to a previous test using an argument matcher against a non-virtual method, or in a Returns statement.

Unfortunately this can be quite tricky to debug. First step is to see if the problem occurs when you run all the test in this fixture. If so, check all uses of Arg.Is|Any in that fixture, starting with the one that runs immediately before the test that fails (if your test framework uses a predictable test order, otherwise you'll need to look at test logs to see what tests proceed the failing one).

If it does not occur with that fixture you'll need to look through the fixtures that run beforehand to see where the left over arg matcher is coming from. It is most likely somewhere near the failing test.

Hope this helps. In positive news the next NSubstitute version (v4) will offer more help in these cases.

See also: How not to use argument matchers.

David Tchepak
  • 9,826
  • 2
  • 56
  • 68
3

In our case, a random test was sending this error message, but only when running all the test. We found this error when migrated from 4.6.1 to netcore 3.1.

The problem was that a test class without any substitute was using the Arg.Any<int>() expresion, for unkown reason.

Deleting this unespected piece of code Arg.Any<int>() was the solution.

Michael H.
  • 3,323
  • 2
  • 23
  • 31
espumita
  • 157
  • 1
  • 6
2

Most likely testDate is an argument matcher (Arg.Is or Arg.Any)

The exception message is telling you just to use argument matchers as member call arguments, not as return values, but you are are using it as return value...

"Do not use in a Returns() statement or anywhere else outside of a member call"

Try

var testDate = new DateTime(); //<-- try setting the desired date as needed
var myDate = Substitute.For<IMyDate>();
myDate.GetDate().Returns(testDate);

Reference NSubstitute: Argument matchers

Nkosi
  • 235,767
  • 35
  • 427
  • 472
MrVoid
  • 709
  • 5
  • 19
  • It gives the same result. See update in my question. –  Apr 05 '18 at 11:30
  • @qwerty I highly doubt that the error will be the same. What is the new error being thrown? – Nkosi Apr 05 '18 at 11:33
  • I just tested it locally and it works fine, as @NKosi said,probably is a different error. – MrVoid Apr 05 '18 at 11:37
  • Don't know what to tell you - it's the same error. testDate was already a hard-coded date beforehand. –  Apr 05 '18 at 11:41
  • That is odd, make sure that recompilation works fine and your are not getting some old binaries where the source code was different – MrVoid Apr 05 '18 at 11:45
  • No - tried restarting VS and deleting the bin and obj directories –  Apr 05 '18 at 12:03
0

To fix this issue, you need to identify the method that causes it, this can be the method you're trying to call or another nested method inside the method you're trying to call...

Making that method virtual fixes this issue.

If you substituted for a class rather than an interface, check that the call to your substitute was on a virtual/abstract member. Return values cannot be configured for non-virtual/non-abstract members.

Noob
  • 710
  • 11
  • 15
0

I faced it problem. And the exception was thrown in one test class (file), but the cause of issue was in different test class (file)

The problem is Arg.Any<>()

    [Test]
    public void CaptureAsync_Success()
    {
        Assert.Throws<NotImplementedException>(() => _sut.CaptureAsync(Arg.Any<string>));
    }

I fixed this issue using the instance of type string

    [Test]
    public void CaptureAsync_Success()
    {
        Assert.Throws<NotImplementedException>(() => _sut.CaptureAsync("test"));
    }
Larissa Savchekoo
  • 6,412
  • 1
  • 13
  • 7