2011-10-24 25 views
2

在我簡單的Index() ActionMethod我引用User.Identity屬性。所以,我認爲我需要嘲笑它。當我嘲笑我的ASP.NET MVC控制器時,我的ActionMethod返回沒有視圖。爲什麼?

所以我創建了一個模擬部分和HomeController使用,在我的單元測試。當我這樣做時,ActionMethod返回null作爲視圖。當我用具體實例替換模擬控制器時(當然註釋掉User.Identity的任何參考),然後返回正確的視圖。

例如。

// Arrange. 
var homeController = Mock<HomeController>(..); 
homeController.Setup(x => x.User).Returns(new GenericPrincipal(..)); 

// Act. 
var result = homeController.Index(); 

// Assert. 
Assert.IsNotNull(result); // This fails here. result is NULL. 

,但我做的時候這一點(和註釋掉任何User參考),它的工作原理...

// Arrange. 
var homeController = new HomeController(..); 

// Act. 
var result = homeController.Index(); 

// Assert. 
Assert.IsNotNull(result); // Tick! 

任何想法,這是爲什麼?

+1

是否使用的是嘲諷庫? –

+0

另外,你在這裏測試什麼?嘲笑圖書館是否工作? –

+0

我正在使用Moq,並且正在測試視圖中返回的一些結果。我沒有測試moq庫本身。我認爲這個問題是因爲模擬控制器沒有上下文和請求的東西,哪些ViewEngine需要? –

回答

2

我想你應該嘲笑一個的HttpContext爲控制器的工作。 I provided one on another answer that you could use。正如Steve Rowbotham所說,你應該嘲笑被測系統的依賴性(即控制器的依賴性),而不是模擬被測系統本身;要測試控制器的真實版不是一個模擬的:)

從鏈路使用HttpContextBase類,你根本就在您的測試

var controllerToTest = new HomeController(); 
var context = new MockHttpContextBase(controllerToTest); 

// do stuff that you want to test e.g. something goes into session 

Assert.IsTrue(context.HttpContext.Session.Count > 0); 

下面你可以走得更遠了一步,創建安裝程序和TearDown方法以使用模擬的上下文來設置控制器。

1

說實話,這看起來像一個非常奇怪的測試,因爲你嘲笑被測系統(SUT),換句話說HomeController。通常人們會嘲笑SUT的依賴關係,在模擬上設置預期,並將模擬注入SUT以確認它與其依賴關係正常交互。

當您創建HomeController的模擬時,Moq正在創建一個繼承自HomeController並覆蓋虛擬方法Index的類。所以,當你調用你不打電話的Index執行您在HomeController類中定義,但覆蓋的一個模擬Index。既然你沒有明確Setup模擬它的方法將返回默認值,在這種情況下,null

在你的第二個測試中,你調用Index的實際實現,因爲你正在構造一個HomeController類的實際實例。如果您在模擬對象的實例調用GetType(),那麼你會發現它是從HomeController其攔截調用基類的公共定義,重寫的方法(這是目的有很大一部分派生的代理實例模擬對象)。

3

有在你的單元測試一些奇怪的事情。您正在對控制器進行單元測試,但是您正在模擬正在測試的對象的創建:var homeController = Mock<HomeController>(..);這是不正確的。

這裏是一個嘲弄用戶注入控制器,你願意到單元測試的正確方法:

// arrange 
var sut = new HomeController(); 
var user = new GenericPrincipal(new GenericIdentity("foo"), null); 
var httpContext = new Mock<HttpContextBase>(); 
httpContext.Setup(x => x.User).Returns(user); 
var context = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), sut); 
sut.ControllerContext = context; 

// act 
var actual = sut.Index(); 

// assert 
... 
+0

乾杯!我會給這個前面的。作爲一邊......嗯..這讓我想起了我在某處看到的一些代碼......它在哪裏。 –

+1

@ Pure.Krome,有[gazillions的地方](http://www.google.com/search?s?hl=en&sugexp=kjrmc&cp=35&gs_id=3l&xhr=t&q=moq%20asp.net%20mvc%20moq% 20user%20controller&PQ = MOQ + asp.net + MVC + MOQ +用戶+控制器&PF = p&sclient = PSY-AB&安全=活性&站點=&源= HP&PBX = 1&OQ =&水溶液=&AQI =&AQL =&gs_sm =&gs_upl =&BAV = on.2,或。通過互聯網,您可以找到這個代碼,並通過互聯網找到這些代碼:r_gc.r_pw。,cf.osb&biw = 1680&bih = 945&ech = 2&psi = K0ilTsrKCYTqOYLE6fwE.1319454763487.4&emsg = NCSR&noj = 1&ei = M0ilTue3J9CXOsfX_L4N)。下面是一個例子:http://www.codethinked.com/simplified-aspnet-mvc-controller-testing-with-moq –

+0

昨晚我在工作後發現了它。它來自NerdDinner - 第12部分:http://nerddinnerbook.s3.amazonaws.com/Part12.htm :) :) –

1

我認爲你的索引方法可能是虛擬的,這會導致Moq用一個模擬函數替換該函數。爲了防止這種情況,您需要在模擬上設置Call​​Base屬性。

但是,我同意其他答覆,你不應該嘲笑你的控制器,但你應該嘲笑你的依賴。

(一個更簡單的方法是創建一個可以從HttpContext的獲取主要的專用模型綁定,那麼你可以通過委託人作爲輸入參數,以你的方法)

相關問題