2009-07-25 140 views
4

我正在使用Moq创建HttpResponseBase的模拟对象。我需要能够测试HttpResponseBase.End()在我的库中被调用。为此,我在通话之前指定了一些文字,之后再指定了一些文字。然后我检查HttpResponseBase.Output中只有调用End()之前的文本。如何模拟HttpResponseBase.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; 
} 

回答

2

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

一般来说,Moq并不特别容易,因为它没有有序期望的概念(与RhinoMocks不同)。但是,有一个feature request for it

您可能可以使用Callback并设置End方法来切换一个标志,该标志确定模拟的任何进一步行为,但它不会特别漂亮。我想是这样的:

bool ended = false; 
var mock = new Mock<HttpResponseBase>(); 
mock.Setup(x => x.End()).Callback(() => ended = true); 
// Other setups involving 'ended' and Callbacks 

然后让其他所有的设置都基于ended是否是真还是假双implementatations。

这将是非常可恶的,所以我会认真考虑我的选择在这一点上。至少有两个方向可以使用:

  1. 假冒HttpResponseBase而不是使用Moq。这听起来像是你正在期待实现的这种特定行为,因此具有嵌入式逻辑的Test Double听起来像是一个更好的选择。简而言之,伪造是一个测试双重行为,它可以包含模仿预期生产实现的半复杂逻辑。您可以在优秀的xUnit Test Patterns书中阅读更多关于假货和其他测试双打的信息。
  2. 重新考虑您的初始假设。在我看来,您正在将您的客户端与HttpResponseBase的特定行为紧密关联,因此您可能违反了Liskov替代原则。不过,我可能会误解,因为一种名为'End'的方法带有超出纯粹语义的某些内涵,但是,我个人认为,如果更好的设计是可能的话。
+0

谢谢!设置一个标志听起来像是最简单的方法。 – 2009-07-26 15:30:39