Страницы

Поиск по вопросам

суббота, 13 июля 2019 г.

Как правильно создавать заглушки для классов с асинхронными методами в Ninject.MockingKernel?

Имеется класс, который использует Ninject для получения экземпляра репозитория:
public class ClosedClass { public String DoWork() { var repo = AppStatic.Kernel.Get(); return repo.GetData(); }
public async Task DoWorkAsync() { var repo = AppStatic.Kernel.Get(); return await repo.GetDataAsync(); } }
Как видно из кода конкретный экземпляр класса, реализующего IRepo каждый экземпляр класса ClosedClass получает от ядра Ninject, экземпляр которого хранится в статическом открытом поле статического класса AppStatic. Вот, собственно, код класса:
public static class AppStatic { public static IKernel Kernel { get; private set; }
static AppStatic() { Kernel = new StandardKernel(); }
public static void SetKernel(IKernel kernelInstance) { Kernel = kernelInstance; } }
Класс ClosedClass необходимо протестировать при помощи MSTest + Ninject + Ninject.MockingKernel + Moq, при чём тестируются оба метода (синхронный DoWork() и асинхронный DoWorkAsync()). Собственно, с тестированием синхронного метода проблем не возникает. Создаётся экземпляр класса, затем ядро Niject, которое позвозяет привязывать моки к интерфейсам, на указанном моке, собственно, указывается желаемое значение:
[TestMethod] public void TestSync() { var c = new SAMPLEMOQ.ClosedClass(); var kernel = new MoqMockingKernel(); kernel .GetMock() .Setup(m => m.GetData()) .Returns("FAKE"); AppStatic.SetKernel(kernel);
Trace.WriteLine(c.DoWork());
}
В результате выполнения теста в output выводится строка FAKE - отлично! Тем не менее, при тестировании асинхронного метода DoWorkAsync() аналогичным образом, тест просто начинает выполнение и не останавливается, пока я сам не отменяю процесс выполнения. Код юнит-теста для асинхронного метода DoWorkAsync()
[TestMethod] public async Task TestASync() { var c = new SAMPLEMOQ.ClosedClass();
var kernel = new MoqMockingKernel();
kernel .GetMock() .Setup(m => m.GetDataAsync()) .Returns(new Task(() => "Fake")); AppStatic.SetKernel(kernel);
Trace.WriteLine(await c.DoWorkAsync()); }
Вопрос: почему этот тест не выполняется, при чём даже не выдаёт никакую ошибку?
PS: Тесты запускаю НЕ параллельно, каждый в отдельности.
OS: Windows 10 IDE: VS 2015 Update 3 Platform: .NET Framework 4.6 Ninject: v3.2.2.0 (net46) Ninject.MockingKernel: v3.2.2.0 (net46) Ninject.MockingKernel.Moq: v3.2.2.0 (net46) Moq: v4.5.2.1 (net46)


Ответ

Попробуйте заменить
kernel .GetMock() .Setup(m => m.GetDataAsync()) .Returns(new Task(() => "Fake"));
на
kernel .GetMock() .Setup(m => m.GetDataAsync()) .Returns(Task.FromResult("Fake"));
или
kernel .GetMock() .Setup(m => m.GetDataAsync()) .Returns( async () => { await Task.Delay(20); return "Fake"; });
(смотря что требуется).
Дело вот в чём. Если убрать всю обвязку, то по сути происходит
await new Task(() => "Fake");
Однако new Task(...) создаёт не стартованную задачу (со статусом Created), такой await не завершится.

Комментариев нет:

Отправить комментарий