2009-08-04 53 views
3

我正在處理ASP.NET MVC應用程序,並試圖針對控制器操作編寫一些單元測試,其中一些操作HttpContext上的屬性,例如Session,Request.Cookies, Response.Cookies等。我在解決如何「安排,行動,斷言」方面遇到了一些麻煩......我可以看到Arrange和Assert ......但我很難弄清楚如何「操作」屬性當它的所有屬性都只有getter時,它是一個模擬的HttpContextBase。我不能設置任何東西在我的控制器操作內我的模擬上下文...所以它似乎不是很有用。我對嘲笑相當陌生,所以我肯定有些東西我缺少,但我認爲我應該能夠創建一個模擬對象,我可以在測試控制器動作的上下文中使用它實際上可以設置屬性值,然後再聲稱他們仍然是我設置它們,或類似的東西。我錯過了什麼?在模擬HttpContextBase上設置屬性

public static HttpContextBase GetMockHttpContext() 
    { 
     var requestCookies = new Mock<HttpCookieCollection>(); 
     var request = new Mock<HttpRequestBase>(); 
     request.Setup(r => r.Cookies).Returns(requestCookies.Object); 
     request.Setup(r => r.Url).Returns(new Uri("http://example.org")); 

     var responseCookies = new Mock<HttpCookieCollection>(); 
     var response = new Mock<HttpResponseBase>(); 
     response.Setup(r => r.Cookies).Returns(responseCookies.Object); 

     var context = new Mock<HttpContextBase>(); 

     context.Setup(ctx => ctx.Request).Returns(request.Object); 
     context.Setup(ctx => ctx.Response).Returns(response.Object); 
     context.Setup(ctx => ctx.Session).Returns(new Mock<HttpSessionStateBase>().Object); 
     context.Setup(ctx => ctx.Server).Returns(new Mock<HttpServerUtilityBase>().Object); 
     context.Setup(ctx => ctx.User).Returns(GetMockMembershipUser()); 
     context.Setup(ctx => ctx.User.Identity).Returns(context.Object.User.Identity); 
     context.Setup(ctx => ctx.Response.Output).Returns(new StringWriter()); 

     return context.Object; 
    } 

回答

2

嘿,我覺得你只是經歷有點脫節這裏,沒什麼大不了的。你所描述的是100%可能的。

我不完全肯定你爲什麼不能在你的Mocks上設置屬性,但是如果你發佈完整的測試代碼,我會很樂意與你一起瀏覽。就在我頭頂,我會建議兩件事:

  1. Setup()和SetupProperty()之間有區別。如果你想跟蹤屬性的值,那麼SetupProperty()可能就是你想要的值,而不是隻從它們那裏獲取值。

  2. 或者嘗試在任何需要設置屬性的模擬上調用SetupAllProperties()。

查看Moq quickstart以及一些示例。

+0

在單元測試使用*這*是非常有益的,謝謝你。我已經通讀了Moq quickstart,但忽略了這些方法/示例,或者誤解了他們打算做的事情。感謝您的澄清。我仍然遇到了一些困難,如何設置我的控制器,以便我可以模擬HttpContext/HttpSession/Request.Cookies對象,並能夠適當地獲取/設置它們,但這是一個有點不同的問題。再次感謝。 – 2009-08-04 04:05:13

4

不確定是否有人有興趣,但我已經將Moq FakeHttpContext翻譯爲使用Rhino Mocks(我選擇的武器)的Moq FakeHttpContext。

public static HttpContextBase FakeHttpContext() 
     { 
      var httpContext = MockRepository.GenerateMock<HttpContextBase>(); 
      var request = MockRepository.GenerateMock<HttpRequestBase>(); 
      var response = MockRepository.GenerateMock<HttpResponseBase>(); 
      var session = MockRepository.GenerateMock<HttpSessionStateBase>(); 
      var server = MockRepository.GenerateMock<HttpServerUtilityBase>(); 
      var cookies = new HttpCookieCollection(); 
      response.Stub(r => r.Cookies).Return(cookies); 
      request.Stub(r => r.Cookies).Return(cookies); 
      request.Stub(r => r.Url).Return(new Uri("http://test.com")); 

      httpContext.Stub(x => x.Server).Return(server); 
      httpContext.Stub(x => x.Session).Return(session); 
      httpContext.Stub(x => x.Request).Return(request); 
      httpContext.Stub(x => x.Response).Return(response); 
      var writer = new StringWriter(); 
      var wr = new SimpleWorkerRequest("", "", "", "", writer); 
      System.Web.HttpContext.Current = new System.Web.HttpContext(wr); 
      return httpContext; 

     } 

_httpContext = FakeHttpContext(); 
var cookieManager = new CookieManager(_httpContext); 
string username = cookieManager.GetUsername(); 
_httpContext.AssertWasCalled(hc => { var dummy = hc.Request; });