我该如何模拟HttpResponseBase.End()方法?

4
我正在使用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个回答

2
我对你试图实现的目标还有点不清楚,但从你的描述中,听起来你正在尝试让你的抽象行为像特定的实现。换句话说,因为HttpResponse.End()具有某种行为,你想让你的模拟对象具有相同的行为?
一般来说,使用Moq做到这一点并不容易,因为它没有有序期望的概念(不像RhinoMocks)。然而,有一个功能请求。
你可能可以使用回调和设置End方法来切换决定模拟对象进一步行为的标志,但这不会特别美观。我想到了这样的代码:
bool ended = false;
var mock = new Mock<HttpResponseBase>();
mock.Setup(x => x.End()).Callback(() => ended = true);
// Other setups involving 'ended' and Callbacks

然后,所有其他的设置都要根据ended是true还是false来进行双重实现。
这会非常丑陋,所以我会认真重新考虑我的选择。你可以采取至少两个方向:
1.制作一个HttpResponseBase的假实现,而不是使用Moq。听起来你期望这种实现具有特定的行为,嵌入逻辑的测试替身似乎是更好的选择。简而言之,Fake是一种测试替身,它可以包含类似于预期生产实现的半复杂逻辑。您可以在优秀的xUnit Test Patterns书中了解更多关于Fakes和其他测试替身的信息。
2.重新考虑您的最初假设。我觉得你将客户端与HttpResponseBase的特定行为紧密联系在一起,因此可能违反了Liskov替换原则。但是,我可能错了,因为一个名为“End”的方法带有超出纯语义的某些含义,但仍然,我个人会考虑是否存在更好的设计。

谢谢!设置一个标志似乎是最简单的方法。 - David Brown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接