单元测试Windows.Web.Http HttpClient与模拟的IHttpFilter和IHttpContent,MockedHttpFilter抛出System.InvalidCastException

1pp*_*pCH 13 c# unit-testing win-universal-app windows-10

我有一个类依赖于Windows.Web.Http(Windows 10 UAP App)中的HttpClient.我想进行单元测试,因此我需要"模拟"HttpClient来设置Get-Call应返回的内容.我开始使用HttpClient进行"简单"的单元测试,使用手写模拟的IHttpFilter和IHttpContent.它没有按预期工作,我在Test-Explorer中得到一个InvalidCastException.

单元测试看起来像:

    [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);
    }
Run Code Online (Sandbox Code Playgroud)

我在MockedHttpFilter中实现了IHttpFilter:

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...
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

我在MockedHttpContent中实现了IHttpContent:

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;
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

Test-Explorer结果视图中的错误:

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.
Run Code Online (Sandbox Code Playgroud)

首先,不确定抛出异常的原因/我做错了什么.也许有人可以指出我正确的方向或提示下一步检查/测试什么?

其次,是否有更好的方法来使用HttpClient依赖(Windows 10 UAP)对代码进行单元测试?

Fab*_*lai 0

看来您没有使用AsTask与返回值匹配的重载httpClient.SendRequestAsync(...)

尝试改变这个

var resultContentTask = await httpClient.SendRequestAsync(new HttpRequestMessage(HttpMethod.Get, new Uri("http://dontcare.ch"))).AsTask().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

对此

var resultContentTask = await httpClient.SendRequestAsync(new HttpRequestMessage(HttpMethod.Get, new Uri("http://dontcare.ch"))).AsTask<IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress>>().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)