mardi 29 septembre 2015

Unit Test Windows.Web.Http HttpClient with mocked IHttpFilter and IHttpContent, MockedHttpFilter throws System.InvalidCastException

I have a class that depends on the HttpClient from Windows.Web.Http (Windows 10 UAP App). I want to unit test and therefore I need to "mock" the HttpClient to setup what a Get-Call should return. I started with a "simple" unit test with a HttpClient using a handwritten-mocked IHttpFilter and IHttpContent. It's not working as expected and I get a InvalidCastException in the Test-Explorer.

The unit test looks like:

    [TestMethod]
    public async Task TestMockedHttpFilter()
    {
        MockedHttpContent mockedContent = new MockedHttpContent("Content from MockedHttpContent");
        MockedHttpFilter mockedHttpFilter = new MockedHttpFilter(HttpStatusCode.Ok, mockedContent);

        HttpClient httpClient = new HttpClient(mockedHttpFilter);
        var resultContentTask = await httpClient.SendRequestAsync(new HttpRequestMessage(HttpMethod.Get, new Uri("http://dontcare.ch"))).AsTask().ConfigureAwait(false);
        // Test stops here, throwing System.InvalidCastException: Specified cast is not valid

        // Code not reached...
        var result = await resultContentTask.Content.ReadAsStringAsync();
        Assert.AreEqual("Content from MockedHttpContent", result);
    }

I implemented IHttpFilter in MockedHttpFilter:

public class MockedHttpFilter : IHttpFilter
{
    private HttpStatusCode _statusCode;
    private IHttpContent _content;

    public MockedHttpFilter(HttpStatusCode statusCode, IHttpContent content)
    {
        _statusCode = statusCode;
        _content = content;
    }

    public IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress> SendRequestAsync(HttpRequestMessage request)
    {
        return AsyncInfo.Run<HttpResponseMessage, HttpProgress>((token, progress) =>
        Task.Run<HttpResponseMessage>(()=>
        {
            HttpResponseMessage response = new HttpResponseMessage(_statusCode);
            response.Content = _content;
            return response; // Exception thrown after return, but not catched by code/debugger...
        }));
    }
}

I implemented IHttpContent in MockedHttpContent:

public class MockedHttpContent : IHttpContent
{
    private string _contentToReturn;

    public MockedHttpContent(string contentToReturn)
    {
        _contentToReturn = contentToReturn;
    }

    public HttpContentHeaderCollection Headers
    {
        get
        {
            return new HttpContentHeaderCollection();
        }
    }

    public IAsyncOperationWithProgress<string, ulong> ReadAsStringAsync()
    {
        return AsyncInfo.Run<string, ulong>((token, progress) => Task.Run<string>(() =>
        {
            return _contentToReturn;
        }));
    }
}

The error in the Test-Explorer result view:

Test Name:  TestMockedHttpFilter
Test FullName:  xxx.UnitTests.xxxHttpClientUnitTests.TestMockedHttpFilter
Test Source:    xxx.UnitTests\xxxHttpClientUnitTests.cs : line 22
Test Outcome:   Failed
Test Duration:  0:00:00.1990313

Result StackTrace:  
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at xxx.UnitTests.xxxHttpClientUnitTests.<TestMockedHttpFilter>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Result Message: Test method xxx.UnitTests.xxxHttpClientUnitTests.TestMockedHttpFilter threw exception: 
System.InvalidCastException: Specified cast is not valid.

First, not sure why the exception is thrown / what I'm doing wrong. Maybe someone can point me in the right direction or give a hint what to check / test next?

Second, is there a better way to unit test code with a HttpClient dependency (Windows 10 UAP)?

Aucun commentaire:

Enregistrer un commentaire