我正在使用Moq来创建HttpResponseBase的模拟对象.我需要能够测试在我的库中调用HttpResponseBase.End().为此,我在调用之前指定了一些文本,之后指定了一些文本.然后我检查在HttpResponseBase.Output中是否只有调用End()之前的文本.
问题是,我无法弄清楚如何模拟HttpResponseBase.End()以便它停止处理,就像在ASP.NET中一样.
public static HttpResponseBase CreateHttpResponseBase() {
var mock = new Mock<HttpResponseBase>();
StringWriter output = new StringWriter();
mock.SetupProperty(x => x.StatusCode);
mock.SetupGet(x => x.Output).Returns(output);
mock.Setup(x => x.End()) /* what do I put here? */;
mock.Setup(x => x.Write(It.IsAny<string>()))
.Callback<string>(s => output.Write(s));
return mock.Object;
}
最佳答案 我有点不清楚你想要实现什么,但从你的描述来看,听起来你试图让你的抽象行为像特定的实现.换句话说,因为HttpResponse.End()有某种行为,你想让你的Mock具有相同的行为吗?
一般来说,使用Moq并不是特别容易,因为它没有有序期望的概念(与RhinoMocks不同).但是,有一个feature request for it.
您可以使用Callback和设置End方法来切换确定Mock的任何进一步行为的标志,但它不会特别漂亮.我在考虑这样的事情:
bool ended = false;
var mock = new Mock<HttpResponseBase>();
mock.Setup(x => x.End()).Callback(() => ended = true);
// Other setups involving 'ended' and Callbacks
然后让所有其他设置具有双重实现,具体取决于end是true还是false.
这将是非常丑陋的,所以我现在认真地重新考虑我的选择.您可以采取至少两个方向:
>制作HttpResponseBase的伪实现,而不是使用Moq.听起来您期望实现的这种特定行为,具有嵌入式逻辑的Test Double听起来像是更好的选择.简而言之,Fake是一个测试双,可以包含模拟预期生产实现的半复杂逻辑.你可以在优秀的xUnit Test Patterns书中阅读更多关于假货和其他测试双打的内容.
>重新考虑您的初步假设.听起来像是你将你的客户与HttpResponseBase的特定行为紧密联系在一起,所以你可能违反了Liskov Substitution Principle.然而,我可能会错,因为一种称为“结束”的方法带有超出纯粹语义的某些内涵,但我仍然会考虑是否有更好的设计.