Search code examples
c#unit-testingmockingnsubstitutearrange-act-assert

Is there a way to cache an Arg.Is<> definition for use in both the "Arrange" and "Act" parts of a test?


I have a test that looks like this:

    [Test]
    public void Blah()
    {
        // Arrange
        // ...
        var thing = new Thing();
        mockRouter.Route(Arg.Is<Transition<Thing>>(x => x != null && x.Subject != null && x.Subject.Equals(thing)));

        // Act
        var result = handler.Handle(thing);

        // Assert
        mockRouter.Received(1).Route(Arg.Is<Transition<Thing>>(x => x != null && x.Subject != null && x.Subject.Equals(thing)));
    }

I would like to cache up the Arg definition in a local variable so I can reuse it in the assert. The point is to reduce the amount of code in the test and make it read a bit more fluidly.

    [Test]
    public void Blah()
    {
        // Arrange
        var thing = new Thing();
        var transitionForThing = Arg.Is<Transition<Thing>>(x => x != null && x.Subject != null && x.Subject.Equals(thing));
        mockRouter.Route(transitionForThing);
        // ...

        // Act
        var result = handler.Handle(thing);

        // Assert
        mockRouter.Received(1).Route(transitionForThing);
    }

This does not seem to work, as the value of transitionForThing is null, and so the assertion fails saying that Received(null) was not called. Is there a way to do this or something similar, or am I stuck with this syntax?


Solution

  • Arg.Is has a parameter of type

    Expression<Predicate<T>>
    

    , so you can define it to reuse

    Expression<Predicate<Transition<Thing>>> predicate = 
      x => x != null && x.Subject != null && x.Subject.Equals(thing));
    

    and use it as

    mockRouter.Route(predicate);
    

    But i really don't understand your situation: you usually mock classes that return some result that you need. I think in your case you only need to check that the method of the mocked class has been called, you don't need to define a mock for the action.