簡體   English   中英

當我模擬ASP.NET MVC控制器時,我的ActionMethod不返回任何視圖。 為什么?

[英]When I mock my ASP.NET MVC controller, my ActionMethod returns no view. Why?

在我簡單的Index() ActionMethod中,我引用了User.Identity屬性。 因此,我認為我需要對此進行嘲笑。

所以我創建了一個模擬的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!

任何想法為什么會這樣?

您的單元測試中有一些奇怪的事情。 您正在對控制器進行單元測試,但是正在var homeController = Mock<HomeController>(..);被測對象的創建: 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
...

我認為您應該模擬HttpContext以便控制器使用。 我提供了另一個可以使用的答案 正如史蒂夫·羅伯瑟姆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); 

您可以更進一步,並創建Setup和TearDown方法以使用模擬的上下文設置控制器。

老實說,這看起來像是一個非常奇怪的測試,因為您正在模擬被測系統(SUT),換句話說就是HomeController 通常,將模擬SUT的依賴關系,設置對模擬的期望,然后將模擬注入SUT以確認其與依賴關系正確交互。

當您創建HomeController的模擬時,Moq將創建一個從HomeController繼承並覆蓋虛擬方法Index 因此,當您在模擬對象上調用Index時,您不是在調用HomeController類中定義的Index的實現,而是調用已重寫的實現。 由於尚未在模擬中顯式Setup方法,因此它將返回默認值,在這種情況下為null

在第二個測試中,您正在調用Index的實際實現,因為您正在構造HomeController類的實際實例。 如果在模擬對象的實例上調用GetType() ,則會看到它是從HomeController派生的代理實例,該代理攔截對基類上公共定義的,可重寫方法的調用(這是模擬對象的目的)。

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

但是,我同意其他答復,即您不應模擬控制器,而應模擬依賴性。

(一個更簡單的方法是創建一個可以從HttpContext提取主體的專用模型綁定程序,然后可以將主體作為輸入參數傳遞給您的方法)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM