HttpResponseBase.Headers пуст при запуске теста - PullRequest
5 голосов
/ 01 ноября 2010

Я использую Moq для создания Mock<HttpResponseBase> для проверки FileResult, который я создаю для своего приложения MVC2.

В методе WriteFile(HttpResponseBase response) FileResult у меня есть следующий код в конце:

// Write the final output with specific encoding.
response.OutputStream.Write(output, 0, output.Length);
response.AppendHeader("Content-Encoding", encoding);

Он будет использовать utf-8 или gzip в зависимости от кодировки из заголовка Accept-Encoding запроса.

Итак, в моем тесте я настроил Mock<HttpResponseBase> так:

var mockResponse = new Mock<HttpResponseBase>();
mockResponse.Setup(r => r.OutputStream).Returns(new MemoryStream());
mockResponse.Setup(r => r.Headers).Returns(new NameValueCollection());

Но когда я действительно проверяю, что заголовок был установлен, Content-Encoding всегда возвращает ноль:

var response = mockResponse.Object;
Assert.AreEqual("utf-8", response.Headers["Content-Encoding"]);

Странно то, что OutputStream получает записанные в него данные, и я могу утверждать, что он записывает правильное значение.

Странно то, что когда я действительно отлаживаю FileResult в веб-проекте, заголовок отправляется правильно.

У кого-нибудь есть понимание этого? Я могу предоставить больше кода при необходимости.

Ответы [ 3 ]

4 голосов
/ 01 ноября 2010

Я закончил тем, что просто насмехался над методом AppendHeader, чтобы принудительно добавить заголовок к заголовкам HttpResponseBase:

mockResponse
    .Setup(r => r.AppendHeader(It.IsAny<string>(), It.IsAny<string>()))
    .Callback((string k, string v) => mockResponse.Object.Headers.Add(k, v));

Я подозреваю, что внутри вызова * 1006 что-то еще внизу* это не любит добавлять заголовки без фактического HttpResponseBase на месте.

Если есть идея получше, не стесняйтесь предлагать.Надеюсь, это поможет кому-то в будущем.

4 голосов
/ 02 ноября 2010

Проблема, с которой вы столкнулись, связана с тем, что вы пытаетесь частично высмеять HttpResponseBase класс.Запись в выходной поток работает, потому что свойство (OutputStream в этом случае) является поддельным и доступным из SUT (тестируемой системы).

Однако, когда вы имитируете свойство Headers, это только то свойствоэто насмехается, а не AppendHeader, что на самом деле делает ваша SUT.Макеты по умолчанию, созданные Moq, просто заглушают все методы и свойства как возвращающие значения по умолчанию, поэтому AppendHeader на самом деле ничего не делает.

Для этого есть два решения: первое - это просто тестирование взаимодействия и мойпредпочтительный подход.Не имитируйте Headers, но вместо этого проверяйте AppendHeader.

Mock<HttpResponseBase> responseMock = new Mock<HttpResponseBase>();
//the rest of response setup
FileResult sut = new MyFileResult();
sut.WriteFile(responseMock.Object);
responseMock.Verify(response=>response.AppendHeader("Content-Encoding", "utf8"));

Второй подход заключается в использовании частичного имитации Moq, который заставил бы объект mock вызывать фактические методы класса, если они не были установленыв явном виде.

Mock<HttpResponseBase> responseMock = new Mock<HttpResponseBase>(){ CallBase = true };
//the rest of response setup
FileResult sut = new MyFileResult();
sut.WriteFile(responseMock.Object);
Assert.AreEqual("utf-8", responseMock.Object.Headers["Content-Encoding"]);

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

2 голосов
/ 01 ноября 2010

На основании предоставленного кода установки (не уверен, что это опечатка), я думаю, что это должно читаться следующим образом

var Response = new Mock<HttpResponseBase>();
Response.Setup(r => r.OutputStream).Returns(new MemoryStream()); 
Response.Setup(r => r.Headers).Returns(new NameValueCollection());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...