Преобразование синхронных моков Moq в асинхронные

Я работаю над преобразованием синхронного кода 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, но у меня были некоторые проблемы с выводом типов, которые я не мог полностью решить. Есть ли стандартный или более простой способ преобразовать такой макет, чтобы лучше обрабатывать асинхронный метод?


person captncraig    schedule 22.08.2012    source источник


Ответы (2)


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

person Kevin Kuszyk    schedule 26.02.2014

Во-первых, именование: асинхронный шаблон на основе задач (TAP) говорит, что все методы, которые являются асинхронными и возвращают Tasks, должны иметь имена, заканчивающиеся на 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));
    }
}
person svick    schedule 23.08.2012