I want to unit test a method that calls another method of a service returning an IAsyncEnumerable<T>
. I have created a a mock of my service Mock<MyService>
and I want to setUp this mock but I don't know how to do that. Is it possible ? Are there other ways of unit testing a method that calls something retuning an IAsyncEnumerable
public async Task<List<String>> MyMethodIWantToTest() { var results = new List<string>(); await foreach(var item in _myService.CallSomethingReturningAsyncStream()) { results.Add(item); } return results; }
I recommend using ToAsyncEnumerable
from System.Linq.Async
, as Jeroen suggested. It seems like you're using Moq, so this would look like:
async Task MyTest() { var mock = new Mock<MyService>(); var mockData = new[] { "first", "second" }; mock.Setup(x => x.CallSomethingReturningAsyncStream()).Returns(mockData.ToAsyncEnumerable()); var sut = new SystemUnderTest(mock.Object); var result = await sut.MyMethodIWantToTest(); // TODO: verify `result` }
If you don’t want to do anything special, e.g. a delayed return which is usually the point of async enumerables, then you can just create a generator function that returns the values for you.
public static async IAsyncEnumerable<string> GetTestValues() { yield return "foo"; yield return "bar"; await Task.CompletedTask; // to make the compiler warning go away }
With that, you can simply create a mock for your service and test your object:
var serviceMock = new Mock<IMyService>(); serviceMock.Setup(s => s.CallSomethingReturningAsyncStream()).Returns(GetTestValues); var thing = new Thing(serviceMock.Object); var result = await thing.MyMethodIWantToTest(); Assert.Equal("foo", result[0]); Assert.Equal("bar", result[1]);
Of course, since you are now using a generator function, you can also make this more complicated and add actual delays, or even include some mechanism to control the yielding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With