Как выполнить универсальную функцию, которая передается в качестве параметра для смоделированной службы - PullRequest
0 голосов
/ 04 января 2019

У меня есть служба, которая реализована в отдельной библиотеке и принимает Func<T> в качестве параметра функции.

При издевательстве над сервисом мне все еще нужен мой Func<T> для запуска.

Как мне настроить макет объекта для этого?

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

// This is the service that is in a different library and I want to mock
public interface IServiceToMock
{
    T ExecuteAsync<T>(Func<T> func);
}

public class ServiceToMock : IServiceToMock
{
    public T ExecuteAsync<T>(Func<T> funcToBeExecuted)
    {
        // does some more logic that I don't want to test
        return funcToBeExecuted();
    }
}

Это потребитель услуги

public class ServiceConsumer
{
    private readonly IServiceToMock service;

    public ServiceConsumer(IServiceToMock service) => this.service = service;

    public async Task Consume()
    {
        await service.ExecuteAsync(async () => await ConsumeInteger(1));
        await service.ExecuteAsync(async () => await ConsumeString("String"));
    }

    // This is the method that I want to be triggered when the Consume() is called
    private async Task ConsumeInteger(int number)
    {
        await new Task<int>(() =>
        {
            Console.WriteLine(number);
            return number;
        });
    }

    // This is the method that I want to be triggered when the Consume() is called
    private async Task ConsumeString(string str)
    {
        await new Task<string>(() =>
        {
            Console.WriteLine(str);
            return str;
        });
    }
}

Это тест, который у меня до сих пор

public class TestServiceConsumer
{
    public void TestMethod()
    {
        var moqLibraryService = new Mock<IServiceToMock>();
        // How can I set up the mock to have the Console 
        moqLibraryService.Setup(ms => ms.ExecuteAsync(It.IsAny<Func<T>>())).Returns(T());
    }
}

1 Ответ

0 голосов
/ 06 января 2019

Я думаю, вы могли бы сделать это:

var moqLibraryService = new Mock<IServiceToMock>();

moqLibraryService.Setup(ms => ms.ExecuteAsync(It.IsAny<Func<int>>()))
  .Returns( (Func<int> f) => f() );
moqLibraryService.Setup(ms => ms.ExecuteAsync(It.IsAny<Func<string>>()))
  .Returns( (Func<string> f) => f() );

Используется перегрузка Returns, которая принимает valueFunction, а не value. Каждый раз, когда происходит насмешка, эта анонимная функция (Func<int> f) => f() будет оцениваться снова. Здесь f - это аргумент «это все», переданный в Moq.

Возможно, это будет труднее сделать, если вы не хотите явно упоминать типы (здесь int, string). Это было бы связано с потоком Mocking универсальных методов в Moq без указания T .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...