Я пытаюсь протестировать асинхронный метод, который имеет такой цикл while:
Код: Выделить всё
public class ClassUnderTest {
private readonly IDependencyToBeMocked _dependency;
ClassUnderTest(IDependencyToBeMocked dependency) {
_dependency = dependency;
}
public async Task MethodToBeTested(CancellationToken token) {
while (!stoppingToken.IsCancellationRequested)
{
await _dependency.Wait();
}
}
}
public interface IDependencyToBeMocked {
Task Wait();
}
Код: Выделить всё
public class Tests
{
private readonly IDependencyToBeMocked _dependency;
private readonly ClassUnderTest _classUnderTest;
public Tests()
{
_dependency = Substitute.For();
_classUnderTest = new ClassUnderTest(_dependency);
}
[Fact]
public async Task Test()
{
// arrange
var source = new CancellationTokenSource();
_dependency.Wait().Returns(Task.CompletedTask);
// act
var task = _classUnderTest.MethodToBeTested(source.Token);
await source.CancelAsync();
await task;
// assert
// do some assertions
}
}
Тестируемый метод никогда не возвращается обратно в вызывающий абонент, несмотря на то, что его не ждут. Я бы ожидал, что при первом нажатии он ожидает _dependent.Wait(), чтобы управление вернулось вызывающему объекту (т. е. методу Test()), но вместо этого он постоянно застревает в цикле while.
Похоже, что происходит какая-то странность: если я изменю это так, _dependent.Wait().Returns(Task.Delay(10)); тест будет выполняться так, как ожидалось; однако, если я использую _dependent.Wait().Returns(Task.Delay(1));, он остается в цикле. Я подозреваю, что это как-то связано с тем, что планировщик задач решает, будет ли await задерживать поток или нет перед возвратом к вызывающему объекту?
Не уверен, что я неправильно понимаю, как работают асинхронные методы. предназначены для насмешек или чего-то в этом роде.
Спасибо!
Подробнее здесь: https://stackoverflow.com/questions/790 ... -to-caller