【问题标题】:Async unit test fail to return a value异步单元测试无法返回值
【发布时间】:2018-08-11 20:33:01
【问题描述】:

我正在使用 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 被调用并返回到被测单元。它继续正确,反序列化并返回没有问题。

但是一旦它返回到我的测试方法中,我可以看到返回的对象不是空的,因为调试器显示了它的类型,但是如果我尝试向下钻取,大约需要 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; }
}

【问题讨论】:

  • 你能给我们看看你的测试吗?

标签: .net unit-testing task moq xunit


【解决方案1】:

这是我的错误,我是在帖子中添加 ObjectMock 类时发现的。我推送的序列化版本是"&lt;ObjectMock testResponse='Test Value'/&gt;",但是在ObjectMock类中,testResponse属性是XmlElement注释的。

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

我想 XmlElement/XmlAttribute 反转导致了一个异常,该异常导致了任务的延迟并导致了超时。

又一个rubber duck debugging赢了!

【讨论】:

  • 感谢您回复我们。我很高兴你发现了问题。 :) 当你得到一分钟时,请将其标记为已接受的答案。
猜你喜欢
  • 2015-12-23
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
  • 2020-07-14
  • 2016-01-26
  • 1970-01-01
  • 2011-11-07
相关资源
最近更新 更多