Макет HttpWebResponse со значением для свойства CharacterSet - PullRequest
0 голосов
/ 10 сентября 2018

Как я могу издеваться над HttpWebResponse со свойством CharacterSet для модульного теста?В моем коде я проверяю 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",

enter image description here

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Зная исходный код , вы можете вручную установить частные свойства класса HttpWebResponse, которые используются в Get-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;
}

Это зависит от внутренней реализации. Таким образом, если Microsoft изменит внутреннюю реализацию класса HttpWebResponse, ваши тесты будут нарушены.

0 голосов
/ 11 сентября 2018

Я провел дальнейшие исследования в этом направлении, и кажется, что вы не сможете делать то, что хотите.Проблема в том, что свойство CharacterSet наследуется с помощью коллекции заголовков.Хотя вы можете переопределить свойство Headers, свойство CharacterSet смотрит прямо на поле.Единственный способ, которым поле сбора заголовка устанавливается в ненулевое значение, - это через внутренний конструктор, который копирует его из чего-то, называемого cordata.

В результате не существует безопасного способа насмешки CharacterSet.Я полагаю, вы могли бы использовать отражение, чтобы найти поле и установить его таким образом, но кажется, что это не будет хорошей идеей, поскольку реализация может измениться и сломать ваш тест.

...