Вопрос по moq, task-parallel-library, c#, unit-testing – Как я могу сказать Moq вернуть задание?

229

у меня есть интерфейс, который объявляет

Task DoSomethingAsync();

используя мои тесты MoqFramework:

[TestMethod()]
public async Task MyAsyncTest()
{
   Mock mock = new Mock();
   mock.Setup(arg => arg.DoSomethingAsync()).Callback(() => {  });
   ...
}

Затем в моем тесте я выполняю код, который вызываетawait DoSomethingAsync(), И тест просто не проходит на этой линии. Что я делаю неправильно?

Когда вы говорите об ошибках теста в этой строке, какую ошибку это вызывает? AlSki
@AlSki, вероятно, исключение NullReferenceException. как вы видетеВот LuckyLikey

Ваш Ответ

4   ответа
34

Аналогичная проблема

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

Task DoSomething(int arg);

симптомы

Мой тестовый модуль не прошел, когда мой сервис тестируетсяawaited призыв к.DoSomething

исправлять

В отличие от принятого ответа, вы не можете позвонить.ReturnsAsync() на вашеSetup() этого метода в этом сценарии, потому что метод возвращает неуниверсальныйTask, скорее, чем .Task

Тем не менее, вы все еще можете использовать.Returns(Task.FromResult(default(object))) на настройке, позволяющей пройти тест.

Подумайте только: если вам нужно вернуть неуниверсальную задачу (не .net 4.6), я бы рассмотрел возврат Task.Delay (1) как простой способ вернуть задачу. Вы также можете имитировать работу, увеличив аргумент времени. stevethethread
21

Вам нужно только добавить.Returns(Task.FromResult(0)); после обратного вызова.

Пример:

mock.Setup(arg => arg.DoSomethingAsync())
    .Callback(() => {  })
    .Returns(Task.FromResult(0));
3

Теперь вы также можете использовать пакет Talentsoft.Moq.SetupAsynchttps://github.com/TalentSoft/Moq.SetupAsync

Который на основе найденных здесь ответов и идей, предложенных Moq, но еще не реализованных здесь:https://github.com/moq/moq4/issues/384, значительно упростить настройку асинхронных методов

Несколько примеров, найденных в предыдущих ответах, сделанных с расширением SetupAsync:

mock.SetupAsync(arg=>arg.DoSomethingAsync());
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Callback(() => {  });
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Throws(new InvalidOperationException());
507

Ваш метод нене имеет никаких обратных вызовов, поэтому нет причин использовать.CallBack(), Вы можете просто вернуть задачу с нужными значениями, используя.Returns() а такжеTask.FromResultНапример:

MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.FromResult(someValue));

Обновление 2014-06-22

Moq 4.2 имеет два новых метода расширения, чтобы помочь с этим.

mock.Setup(arg=>arg.DoSomethingAsync())
    .ReturnsAsync(someValue);

mock.Setup(arg=>arg.DoSomethingAsync())        
    .ThrowsAsync(new InvalidOperationException());

Обновление 2016-05-05

Как упоминает Сет Флауэрс вдругой ответ,ReturnsAsync доступно только для методов, которые возвращаютTask, Для методов, которые возвращают только Задачу,

.Returns(Task.FromResult(default(object)))

может быть использован.

Как показано вэтот ответв .NET 4.6 это упрощается до.Returns(Task.CompletedTask);Например:

mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.CompletedTask);
Спасибо за актуальность этого ответа, так как фреймворк Moq получил обновления! Jacob Stamm
.Returns(Task.FromResult(default(object)) хорошо работает, когда возвращаемый тип void..Returns(Task.FromResult(null as MyType)) хорошо работает, когда ожидаемый тип возвращаемого значения равен нулю. Jeremy Ray Brown
ReturnsAsync прекрасно работает. Sully
@JeremyRayBrown, как я объясняю, в .NET 4.6default(object) больше не нужен.null as MyType такой же какdefault(MyType) покаMyType является ссылочным типом Panagiotis Kanavos

Похожие вопросы