Завершение работы async Task в Moq Framework

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

Task DoSomethingAsync();

Я использую MoqFramework для своих тестов:

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

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

Ответ 1

В вашем методе нет обратных вызовов, поэтому нет смысла использовать .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

Поскольку Seth Flowers упоминает в другом ответе, ReturnsAsync доступен только для методов, возвращающих Task<T>. Для методов, возвращающих только задачу,

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

.

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

mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.CompletedTask);

Ответ 2

Похожие проблемы

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

Task DoSomething(int arg);

Симптомы

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

Fix

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

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

Ответ 3

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

Пример:

mock.Setup(arg => arg.DoSomethingAsync())
    .Callback(() => { <my code here> })
    .Returns(Task.FromResult(0));