1

I would like to test if function received a specific delegate as parameter. Is it possible in NUnit with NSubstitute?

My interface:

public interface IMyInterface
{
    void Sort(Func<IEnumerable<int>, IOrderedEnumerable<int>> f);
}

My test class:

[TestFixture]
public class Class1
{
    [Test]
    public void Sort_WhenCalled_CallsWithPassedArgument()
    {
        // Arrange
        IMyInterface mock = Substitute.For<IMyInterface>();

        // Act
        mock.Sort(x => x.OrderBy(y => y));

        // Assert
        mock.Received().Sort(x => x.OrderBy(y => y));
    }
}

I also tried with argument matchers, but it always fails.

alcohol is evil
  • 686
  • 12
  • 34
  • 2
    For reference [NSubstitute - Testing for a specific linq expression](http://stackoverflow.com/questions/5654053/nsubstitute-testing-for-a-specific-linq-expression) – Jason Evans Feb 14 '17 at 18:22
  • Thank you. It's not what I expected, but now I know that it's not as simple as I thought. – alcohol is evil Feb 14 '17 at 18:33

1 Answers1

0

The challenge is that your argument type is Func<>, not Expression<Func<>>. With Expression you could inspect the tree to check method names etc.

However, you can unit test against the concrete example for OrderBy (e.g. as opposed to OrderByDescending(), because given a collection of ints 6,4 OrderBy() will always re-sort it to be 4,6. So the following works:

  [TestFixture]
  public class Class1
  {
    [Test]
    public void Sort_WhenCalled_CallsWithPassedArgument()
    {
      // Arrange
      IMyInterface mock = Substitute.For<IMyInterface>();

      Func<IEnumerable<int>, IOrderedEnumerable<int>> func = null;
      mock.WhenForAnyArgs(x => x.Sort(Arg.Any<Func<IEnumerable<int>, IOrderedEnumerable<int>>>())).Do(
        x =>
          {
            func = x.Arg<Func<IEnumerable<int>, IOrderedEnumerable<int>>>();
          });

      // Act
      mock.Sort(x => x.OrderBy(y => y));

      // Assert
      var result = func(new[] { 6, 4 });

      Assert.That(result.FirstOrDefault(), Is.Not.EqualTo(6));
      Assert.That(result.FirstOrDefault(), Is.EqualTo(4));
    }
  }

Of course, the logic is somewhat fragile, so you need to decide if you really want to test that an exact method is used in a func (and then maybe refactor the code to allow to check for this specific method by other means or switch to Expression) or just the behaviour is enough for you.

zaitsman
  • 8,984
  • 6
  • 47
  • 79