Подтвердить что ты не робот

Преобразование синхронных Moq mocks в async

Я работаю над преобразованием тела синхронного кода asp.net в .net 4.5 и новый синтаксис асинхронизации.

У меня есть много тестового кода, который выглядит так:

var retVal = new Foo(bar,baz);
_myMock.Setup(x => x.DoSomething(123)).Returns(retVal);

Когда я конвертирую подпись DoSomething с Foo DoSomething() в async Task<Foo> DoSomething(), весь мой тестовый код должен быть перезаписан. Моим текущим обходным путем является преобразование исходного кода в нечто вроде:

var retVal = new Foo(bar,baz);
_myMock.Setup(x => x.DoSomething(123))
   .Returns(new Task<Foo>(()=>retVal));

Это не особо сложное преобразование, но утомительно, когда у меня есть тысячи тестов, которые необходимо обновить.

Я попробовал сделать метод расширения, называемый ReturnsAsync, чтобы сделать некоторую часть этой формы m, но у меня были некоторые проблемы с допуском типа, которые я не мог полностью прибить. Есть ли стандартный или более простой способ преобразования такого макета, чтобы лучше обрабатывать метод асинхронизации?

4b9b3361

Ответ 1

Moq 4.2 добавил метод расширения ReturnsAsync(), поэтому вам больше не нужно добавлять свои собственные.

Ответ 2

Во-первых, именование: Асинхронный шаблон на основе задач (TAP) говорит, что все методы, которые являются асинхронными и возвращают Task, должны быть именованы с помощью Async. Итак, ваш метод должен быть назван DoSomethingAsync.

Во-вторых, конструктор Task создает Task, который не запускается, вы должны Start() его вручную. Если ваш фактический метод DoSomething делает это тоже, это снова не следует за TAP, и это означает, что ваш код не будет работать с await. Вместо этого вы должны использовать Task.Run(() => value) или, что еще лучше, Task.FromResult(value).

В-третьих, было бы лучше, если бы вы показали нам свой код, который не сработал, чтобы мы могли сказать вам, где вы допустили ошибку.

Теперь тело метода расширения ReturnsAsync() довольно простое, но большая часть работы для меня заключалась в определении правильных типов (тем более, что я не знаю Moq). Код выглядит следующим образом:

public static class MoqExtensions
{
    public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(
        this IReturns<TMock, Task<TResult>> setup, TResult value)
        where TMock : class
    {
        return setup.Returns(Task.FromResult(value));
    }
}