![](/img/trans.png)
[英]MVC ASP.NET Getting back my ViewData.Model in my View when I submit to a Controller
[英]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用模擬函數替換該函數。 為了防止這種情況,您需要在模擬上設置CallBase屬性。
但是,我同意其他答復,即您不應模擬控制器,而應模擬依賴性。
(一個更簡單的方法是創建一個可以從HttpContext提取主體的專用模型綁定程序,然后可以將主體作為輸入參數傳遞給您的方法)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.