NSubstitute icon indicating copy to clipboard operation
NSubstitute copied to clipboard

Create a spy of Func<> and make it return a specific value for testing

Open hicks86 opened this issue 1 year ago • 2 comments

Question Hi all,

Been bashing my head against a desk on this one, cannot seem to figure it out. Essentially I have a method that takes in a Func<T>. I want to be able to define what that func returns and then check if that func has been called in the code. For example:


public class DoIt
{
   public bool Execute(Func<int, int, bool> func)
   {
      return func(1,2);
   }
}

...

[TestMethod]
public void TestIt
{
   var it = new DoIt();
   Func<int, int, bool> funcSpy = Substitute.For<Func<int, int, bool>>();

   funcSpy.Returns((d, dd) => true); //When I do this I get a CouldNotSetReturnDueToLastCallException
   //or
   funcSpy.Invoke(Arg.Any<int>(), Arg.Any<int>()).Returns(true); //When I do this I get RedundantArgumentMatcherException


   var actual = it.Execute(funcSpy);

   actual.Should().BeTrue();
   funcSpy.Received(1).Invoke(Arg.Any<int>(), Arg.Any<int>());
  
}

Thanks

Related links Found some links that helped with the assertion part and another hinted how do do the func but can't get it to work for my scenario

  • https://stackoverflow.com/questions/33017510/mock-result-from-func-with-nsubstitute
  • link 2

hicks86 avatar Oct 18 '23 14:10 hicks86

Version 2 works for me without RedundantArgumentMatcherException and is the right syntax.

Personally I would ask if it is really a good thing to use a mocking framework for this test? Why not just write the test without it?

E.g.:

  [TestMethod]
  public void TestIt()
  {
    var it = new DoIt();

    int? value1 = null;
    int? value2 = null;


    var actual = it.Execute((x, y) =>
    {
      value1 = x;
      value2 = y;

      return true;
    });

    actual.Should().BeTrue();
    value1.Should().Be(1);
    value2.Should().Be(2);
  }

Not as fancy as the NSubstitute version but way easier to understand.

GeraldLx avatar Oct 19 '23 14:10 GeraldLx

Thank you, so the 2nd way is probably what I need to go for, maybe I need an update.

But yeah you make a good point, I can do all that funky mocking manually and at least I have control and know what it is doing. Damn I fell back into the "mock all the things" trap.

Cheers

hicks86 avatar Oct 19 '23 14:10 hicks86

I think the question has been answered and therefore I will close this one.

Please let us know if you need further information or would like us to take another look at this

304NotModified avatar Apr 29 '24 11:04 304NotModified