Установите метод ложного класса для выполнения параметра Fun c<Task> с помощью Moq - PullRequest
0 голосов
/ 02 апреля 2020

Я пишу модульные тесты, в которых используется сервисный метод, который принимает параметр Func<Task> и выполняет его при некоторых условиях.

Метод выглядит следующим образом:

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

      await func();
   }
}

служба, вызывающая метод TryExecute, выглядит следующим образом:

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");
   }
}

Пример неудачного модульного теста, включающий попытку установить поддельный результат при вызове TryExecute, выглядит следующим образом:

[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

}

Проблема: во время выполнения теста privateFunction, переданный в TryExecute, не выполняется (т. Е. При отладке я не могу войти в метод privateFunction, переданный в).

Пожалуйста, дайте мне знать, если есть что-то еще, что я могу уточнить; это мой первый вопрос по StackOverflow.

1 Ответ

1 голос
/ 02 апреля 2020

Попробуйте изменить сигнатуру MethodThatCallsTryExecute(Bar bar), чтобы получить Task вместо void (если оно есть), остальная часть кода должна, как и ожидалось, только что проверила, что privateFunction 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");
    }
}

Сигнатура метода тестирования (или любого другого метода, который вызывает MethodThatCallsTryExecute) должна быть обновлена ​​для получения результата Task, например

[Fact]
public async Task TestName()
{
}
...