IAsyncEnumerable<T>
を返すサービスの別のメソッドを呼び出すメソッドを単体テストしたい。サービスMock<MyService>
のモックを作成しました。このモックを設定したいのですが、方法がわかりません。出来ますか ? IAsyncEnumerable
の再調整を呼び出すメソッドを単体テストする他の方法はありますか
public async Task<List<String>> MyMethodIWantToTest()
{
var results = new List<string>();
await foreach(var item in _myService.CallSomethingReturningAsyncStream())
{
results.Add(item);
}
return results;
}
これを解決する1つの方法は、同期的に列挙されるIEnumerable
をラップする専用のテストクラスを使用することです。
TestAsyncEnumerable.cs
internal class TestAsyncEnumerable<T> : List<T>, IAsyncEnumerable<T>
{
public TestAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable) { }
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new TestAsyncEnumerator<T>(GetEnumerator());
}
internal class TestAsyncEnumerator<T> : IAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(_inner.MoveNext());
public T Current => _inner.Current;
public ValueTask DisposeAsync()
{
_inner.Dispose();
return new ValueTask(Task.CompletedTask);
}
}
使用法:
[Fact]
public async Task MyTest() {
var myItemRepository = A.Fake<IMyItemRepository>();
A.CallTo( () => myRepository.GetAll())
.ReturnsLazily(() => new TestAsyncEnumerable<MyItem>(new List<MyItem> { new MyItem(), ... }));
//////////////////
/// ACT & ASSERT
////////
}