2010-06-18 28 views
5

我很難測試控制器。原來我的測試控制器看起來是這樣的:asp.net mvc如何正確測試控制器

SomethingController CreateSomethingController() 
{ 
    var somethingData = FakeSomethingData.CreateFakeData(); 
    var fakeRepository = FakeRepository.Create(); 

    var controller = new SomethingController(fakeRepository); 

    return controller; 
} 

也能正常工作,爲廣大的測試,直到我得到的代碼Request.IsAjaxRequest()部分。所以我不得不模擬HttpContext和HttpRequestBase。所以,我的代碼則改爲樣子:

public class FakeHttpContext : HttpContextBase 
{ 
    bool _isAjaxRequest; 

    public FakeHttpContext(bool isAjaxRequest = false) 
    { 
     _isAjaxRequest = isAjaxRequest; 
    } 

    public override HttpRequestBase Request 
    { 
     get 
     { 
      string ajaxRequestHeader = ""; 

      if (_isAjaxRequest) 
       ajaxRequestHeader = "XMLHttpRequest"; 

      var request = new Mock<HttpRequestBase>(); 
      request.SetupGet(x => x.Headers).Returns(new WebHeaderCollection 
      { 
       {"X-Requested-With", ajaxRequestHeader} 
      }); 

      request.SetupGet(x => x["X-Requested-With"]).Returns(ajaxRequestHeader); 

      return request.Object; 
     } 
    } 

    private IPrincipal _user; 

    public override IPrincipal User 
    { 
     get 
     { 
      if (_user == null) 
      { 
       _user = new FakePrincipal(); 
      } 
      return _user; 
     } 
     set 
     { 
      _user = value; 
     } 
    } 
} 


SomethingController CreateSomethingController() 
{ 
    var somethingData = FakeSomethingData.CreateFakeData(); 
    var fakeRepository = FakeRepository.Create(); 

    var controller = new SomethingController(fakeRepository); 

    ControllerContext controllerContext = new ControllerContext(new FakeHttpContext(isAjaxRequest), new RouteData(), controller); 
    controller.ControllerContext = controllerContext; 

    return controller; 
} 

現在,它得在我的控制,我打電話Url.RouteUrl爲空這一階段。所以看起來我需要開始模擬我的控制器的路線。

我似乎花費更多的時間搜索如何僞造/模擬對象,然後調試,以確保我的假貨比實際編寫測試代碼更正確。有沒有更簡單的方法來測試控制器?我從MvcContrib看了一下TestControllerBuilder,它幫助解決了一些問題,但似乎並沒有做任何事情。是否還有其他可用的工具可以完成這項工作,並讓我專注於編寫測試而不是寫作嘲弄?

感謝

+1

問題不在於您的測試,它與您的控制器操作。您應該儘量避免在您的操作中使用http上下文,並只使用您在構造函數中提供的依賴關係。行動應該很小。 – 2010-06-18 10:54:39

回答

1

您可以使用一些給你開箱一些這些對象的庫。例如RhinoMock,NMock ...等我親自使用Moq - 這是很好,免費。我最喜歡Moq的是linq表達式。

1

大多數嘲笑引擎會爲你做這一切。我使用RhinoMocks,但有更多的可用。另外Moles是非常新的和有趣的嘲笑引擎(這通常與你的單元測試阿森納更多的彈藥Pex一起)

1

而是嘲諷的東西,你可以通過IAjaxRequest到構造函數。或者使它成爲基礎構造函數類屬性(並使用屬性注入)。或者你可以讓你的構造函數實現IAjaxRequest,然後在基本構造函數類上應用全局動作過濾器,這將設置IAjaxRequest。

這將有助於抽象很多東西,包括HttpContext的東西。不要抽象IHttpContext,抽象IUserContext,ISessionStorage,IAuthentication,IRequestDetails ...

另一種方法是直接在需要特定信息的方法上使用模型聯編程序。例如,請參閱this post。你可以製作一個活頁夾,它會給你IsAjaxRequest,然後你只需要採取行動來接受這個參數。工作得很好,因爲信息完全提供給需要它的方法,而不是整個控制器。