我如何模拟HttpResponseBase.End()?

时间:2009-07-25 21:33:22

标签: c# unit-testing moq

我正在使用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;
}

1 个答案:

答案 0 :(得分:2)

我有点不清楚你想要实现的是什么,但从你的描述来看,听起来你正试图让你的抽象表现得像一个特定的实现。换句话说,因为HttpResponse.End()有某种行为,你希望你的模拟具有相同的行为吗?

总的来说,使用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

然后让所有其他设置根据ended是真还是假来实现双重实现。

这将是非常丑陋的,所以我现在认真地重新考虑我的选择。您至少可以采取两个方向:

  1. 制作HttpResponseBase的伪实现,而不是使用Moq。听起来您期望实现的这种特定行为,具有嵌入式逻辑的Test Double听起来像是更好的选择。简而言之,Fake是一个测试双,可以包含模拟预期生产实现的半复杂逻辑。您可以在优秀的xUnit Test Patterns一书中阅读有关假货和其他测试双打的更多信息。
  2. 重新考虑您的初步假设。听起来像是你将你的客户与HttpResponseBase的特定行为紧密联系在一起,所以你可能违反了Liskov Substitution Principle。但是,我可能会误解,因为一种名为“结束”的方法带有超出纯粹语义的某些内涵,但我仍然会考虑是否有更好的设计。