首页 > 解决方案 > 使用 CharacterSet 属性的值模拟 HttpWebResponse

问题描述

如何使用属性 CharacterSet 模拟 HttpWebResponse 以进行单元测试?在我的代码中,我正在检查 HttpWebResponse.CharacterSet ,如下所示。我可以模拟 HttpWebResponse 但在获取属性“CharacterSet”时获得空引用异常。请注意,我无法在模拟中设置“CharacterSet”,因为它是只读且非虚拟属性。我正在使用.Net 4.6.1

public string ReadResponse(HttpWebResponse response)
    {
        var encoding = (response.CharacterSet == null || response.CharacterSet == "") ? Encoding.UTF8 : Encoding.GetEncoding(response.CharacterSet);
        using (var stream = response.GetResponseStream())
        {
            var reader = new StreamReader(stream, encoding);
            var responseString = reader.ReadToEnd();
            return responseString;
        }
    }

我为 HttpWebReponse 写的模拟是,

public static HttpWebResponse CreateRequestWithResponse(string responseContent)
    {

        var response = new Mock<HttpWebResponse>(MockBehavior.Loose);
        var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(responseContent));
        response.Setup(c => c.StatusCode).Returns(HttpStatusCode.OK);
        response.Setup(c => c.ContentType).Returns("text/xml;charset=\"utf-8\"");
        response.Setup(c => c.GetResponseStream()).Returns(responseStream);

        var request = new Mock<HttpWebRequest>();
        request.Setup(a => a.ContentType).Returns("text/xml;charset=\"utf-8\"");
        request.Setup(s => s.GetResponse()).Returns(response.Object);

        return response.Object;
    }

这是我在获取“CharacterSet”时遇到的错误,

在此处输入图像描述

标签: c#restunit-testingmoqmstest

解决方案


了解源代码后,您可以手动设置在属性的HttpWebResponseGet-Handler 中使用的类的私有CharacterSet属性:

public static HttpWebResponse CreateRequestWithResponse(string responseContent)
{
    var response = new Mock<HttpWebResponse>(MockBehavior.Loose);
    var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(responseContent));
    response.Setup(c => c.StatusCode).Returns(HttpStatusCode.OK);
    response.Setup(c => c.ContentType).Returns("text/xml;charset=\"utf-8\"");
    response.Setup(c => c.GetResponseStream()).Returns(responseStream);

    HttpWebResponse result = response.Object;

    // Set private field behind CharacterSet property
    var prop = typeof(HttpWebResponse).GetField("m_CharacterSet", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    prop.SetValue(result, "utf-8");

    // Set private field used in CharacterSet getter
    prop = typeof(HttpWebResponse).GetField("m_HttpResponseHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    prop.SetValue(result, new WebHeaderCollection());

    return result;
}

这取决于内部实现。所以,如果微软改变了HttpWebResponse类的内部实现,你的测试就会被破坏。


推荐阅读