异步单元测试无法返回值

时间:2018-08-11 20:33:02

标签: .net unit-testing task moq xunit

我正在使用Moq和xUnit为UWP应用程序编写单元测试。我用以下代码编写了一个自定义HttpClient模拟和响应消息:

public sealed class HttpClientMock : IHttpClient
{
    private string _response;

    public HttpClientMock(string response)
    {
        _response = response;
    }

    public bool SimulateBasStatusCode { get; set; }

    public TimeSpan Timeout { get; set; }

    public void Dispose()
    { }

    public async Task<IHttpResponseMessage> GetAsync(string request)
    {
        IHttpResponseMessage response = new HttpResponseMessageMock(_response);

        return await Task.FromResult(response);
    }
}

public sealed class HttpResponseMessageMock : IHttpResponseMessage
{
    private string _response;

    public HttpResponseMessageMock(string response)
    {
        _response = response;
    }

    public bool SimulateBadSuccessStatusCode { get; set; }

    public bool IsSuccessStatusCode
    {
        get
        {
            return !SimulateBadSuccessStatusCode;
        }
    }

    public async Task<string> ReadAsStringAsync()
    {
        return await Task.FromResult(_response);
    }
}

被测单位是这样的:

internal async Task<T> GetAndSerialize<T>(string request)
{
    T res = default(T);

    using (_httpClient)
    {
        _httpClient.Timeout = TimeSpan.FromMinutes(3);
        IHttpResponseMessage response = await _httpClient.GetAsync(request);

        if (response.IsSuccessStatusCode)
        {
            string xml = await response.ReadAsStringAsync();
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            StringReader reader = new StringReader(xml);

            res = (T)serializer.Deserialize(reader);
        }
    }

    return res;
}

在最后一个类中,_httpClient被推送到测试类构造函数下的单元,在这种情况下,它是我的HttpClientMock类。

启动测试时,可以看到正在调用GetAndSerialize。然后,它调用HttpClientMock并正确返回HttpResponseMessageMock的实例,但调试器开始变得非常缓慢,并抱怨System.Threadind.Tasks.Task.SetNotificationForWaitCompletion超时。

我继续,可以看到我的HttpResponseMessageMock的ReadAsStringAsync被调用并返回到被测单元中。它可以正确继续,可以反序列化,然后可以正常返回。

但是一旦返回到我的测试方法中,我就可以看到返回的对象不是null,因为调试器显示了它的类型,但是如果我尝试向下钻取,则大约需要5秒钟并且仅显示“?”。没有显示属性。

稍后在测试中,我对返回的对象的属性进行断言,并将其视为null。

我尝试并搜索了三个小时,但均未成功。你有什么建议吗?

这是测试类的缩写版本:

public class TestClass
{
    private const string OBJECT_MOCK = "<ObjectMock testResponse='Test Value'/>";

    [Fact]
    public async Task FailTest()
    {
        /////
        // Arrange

        IHttpClient httpClient = new HttpClientMock(OBJECT_MOCK);
        TestedService mySvc = new TestesService(httpClient);

        /////
        // Act

        ObjectMock response = await mySvc.GetAndSerialize<ObjectMock>("/TestRelativeURL");

        /////
        // Assert

        Assert.NotNull(response);
        Assert.Equal("Test Value", response.TestResponse);
    }
}

这是ObjectMock类:

[Serializable]
[XmlRoot("ObjectMock")]
public sealed class ObjectMock
{
    [XmlElement("testResponse")]
    public string TestResponse { get; set; }
}

1 个答案:

答案 0 :(得分:1)

这是我的错误,是在帖子中添加ObjectMock类时发现的。我推送的序列化版本为for,但是在ObjectMock类中,testResponse属性被注释为XmlElement。

当我将其更正为XmlAttribute时,不再有延迟,没有SetNotificationForWaitCompletion超时,并且在我的测试方法中正确声明了属性值。

我想XmlElement / XmlAttribute反转会导致异常,从而导致任务延迟并导致超时。

另一个rubber duck debugging获胜!