Проблема, с которой вы столкнулись, связана с тем, что вы пытаетесь частично высмеять 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
, однако, это почти имеет смысл, поскольку его конструктор защищен, поэтому, создавая макет, вы в основном извлекаете его из строки, без необходимости вручную писать двойной тест.