Search code examples
unit-testingwindows-runtimewinrt-async

Mocking DataReader for Windows Store Unit Test project


I'm trying to unit test a Windows Store Class Library project which uses the IDataReader.LoadAsync method. I am able to create my own stub which implements all the parts of IDataReader I need, except for the return type of the LoadAsync method - DataReaderLoadOperation. This is a sealed class with no public constructors, so I don't know what to return from my stub's LoadAsync method.

The code I'm testing doesn't use the result of LoadAsync except to await it, so I tried returning null from my stub. However, this throws an AggregateException because the framework tries to convert the null DataReaderLoadOperation (which is an IAsyncOperation<uint>) into a Task and triggers a NullReferenceException.

It seems Microsoft Fakes is not available for Store unit test projects either, only for regular unit test projects, so that doesn't help either.

How can I mock DataReader.LoadAsync for a Windows Store unit test project?


EDIT: Per Stephen's answer, I mocked IInputStream instead. Below is my mock for reference.

internal class InputStreamStub : IInputStream
{
    public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
    {
        return
            AsyncInfo.Run<IBuffer, uint>
            (
                (token, progress) =>
                    Task.Run<IBuffer>
                    (
                        () =>
                        {
                            progress.Report(0);
                            token.ThrowIfCancellationRequested();
                            var source = Encoding.UTF8.GetBytes(reads.Dequeue());
                            Assert.IsTrue(buffer.Capacity > source.Length); // For the purposes of the unit test, the buffer is always big enough
                            if (source.Length > 0) // CopyTo throws an exception for an empty source
                                source.CopyTo(buffer);
                            buffer.Length = (uint) source.Length;
                            progress.Report(100);
                            return buffer;
                        },
                        token
                    )
            );
    }

    public void Dispose()
    {
    }

    private Queue<string> reads = new Queue<string>(new[]
    {
        "Line1\r\nLine",
        "2\r\nLine3\r",
        "\nLine4",
        "",
        "\r\n",
        "Line5",
        "\r\n",
        "Line6\r\nLine7\r\nLine8\r\nL",
        "ine9\r",
        "\n"
    });
}

Solution

  • I recommend mocking the underlying stream and using a regular DataReader over your mocked stream.