2009-07-25 131 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