简体   繁体   中英

Setup a mocked class method to execute a Func<Task> parameter using Moq

I am writing unit tests that involves a service method that takes in a Func<Task> parameter and executes it under some conditions.

The method looks like this:

public class ServiceA : IServiceA
{
   public async Task TryExecute(Func<Task> func, string foo)
   {
      // ... do unimportant things relating to string foo

      await func();
   }
}

The service calling the TryExecute method looks like this

public class ServiceB : IServiceB
{
   private readonly IServiceA _serviceA;

   public ServiceB(IServiceA serviceA)
   {
      _serviceA = serviceA;
   }

   public async MethodThatCallsTryExecute(Bar bar)
   {
      // ... do unimportant things relating to bar

      await _serviceA.TryExecute(privateFunction, "baz");
   }
}

An example failing unit test including the attempt to set up the mocked outcome when calling TryExecute looks like this:

[Fact]
public async void TestName()
{
   // Arrange
   var serviceA = new Mock<IServiceA>();

   serviceA.Setup(a => a.TryExecute(It.IsAny<Func<Task>>(), It.IsAny<string>()))
      .Returns(async (Func<Task> func, string foo) => { await func(); });

   var serviceB = new ServiceB(serviceA.Object);

   var bar = new Bar();

   // Act
   await serviceB.MethodThatCallsTryExecute(bar);

   // Assert
   ... failing assertions

}

Problem: during test execution, the privateFunction passed into TryExecute is not being executed (ie when debugging, I'm unable to step in the privateFunction method passed in).

Please let me know if there is anything more I can elaborate on; this is my first question on StackOverflow.

Try to change the signature of MethodThatCallsTryExecute(Bar bar) to return a Task instead of void (if it is), the rest of code should work as expected, just checked that privateFunction is invoked

public interface IServiceB
{
    Task MethodThatCallsTryExecute(Bar bar);
}

public class ServiceB : IServiceB
{
    private readonly IServiceA _serviceA;

    public ServiceB(IServiceA serviceA)
    {
        _serviceA = serviceA;
    }

    public async Task MethodThatCallsTryExecute(Bar bar)
    {
        // ... do unimportant things relating to bar

        Func<Task> privateFunction = () => Task.CompletedTask;
        await _serviceA.TryExecute(privateFunction , "baz");
    }
}

The signature of test method (or any other method, which invokes MethodThatCallsTryExecute ) should be updated to return a Task , for example

[Fact]
public async Task TestName()
{
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM