How do you mock an IAsyncEnumerable?

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.


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`
}

It really depends on which mocking framework your using. But, it would be something simple like this example using Moq

var data = new [] {1,2,3,4};
var mockSvc = new Mock<MyService>();
mockSvc.Setup(obj => obj.CallSomethingReturningAsyncStream()).Returns(data.ToAsyncEnumerable());