2009-11-23 86 views

回答

14

我一直在使用下面的Mock和Moq來允許在我的單元測試中設置各種條件。首先,HttpContextBase模擬:

public static Mock<HttpContextBase> GetHttpContextMock(bool isLoggedIn) 
    { 
     var context = new Mock<HttpContextBase>(); 
     var request = new Mock<HttpRequestBase>(); 
     var response = new Mock<HttpResponseBase>(); 
     var session = new Mock<HttpSessionStateBase>(); 
     var server = new Mock<HttpServerUtilityBase>(); 
     var principal = AuthenticationAndAuthorization.GetPrincipleMock(isLoggedIn); 

     context.SetupGet(c => c.Request).Returns(request.Object); 
     context.SetupGet(c => c.Response).Returns(response.Object); 
     context.SetupGet(c => c.Session).Returns(session.Object); 
     context.SetupGet(c => c.Server).Returns(server.Object); 
     context.SetupGet(c => c.User).Returns(principal.Object); 

     return context; 
    } 

每個屬性可能提供一個有用的模擬在這裏成立。這樣一來,如果我需要添加類似引薦,我可以只使用:

Mock.Get(controller.Request).Setup(s => s.UrlReferrer).Returns(new Uri("http://blah.com/"); 

的「GetPrincipleMock」的方法就是建立用戶。它看起來像這樣:

public static Mock<IPrincipal> GetPrincipleMock(bool isLoggedIn) 
    { 
     var mock = new Mock<IPrincipal>(); 

     mock.SetupGet(i => i.Identity).Returns(GetIdentityMock(isLoggedIn).Object); 
     mock.Setup(i => i.IsInRole(It.IsAny<string>())).Returns(false); 

     return mock; 
    } 

    public static Mock<IIdentity> GetIdentityMock(bool isLoggedIn) 
    { 
     var mock = new Mock<IIdentity>(); 

     mock.SetupGet(i => i.AuthenticationType).Returns(isLoggedIn ? "Mock Identity" : null); 
     mock.SetupGet(i => i.IsAuthenticated).Returns(isLoggedIn); 
     mock.SetupGet(i => i.Name).Returns(isLoggedIn ? "testuser" : null); 

     return mock; 
    } 

現在,在測試我的控制器的設置是這樣的:

var controller = new ProductController(); 
var httpContext = GetHttpContextMock(true); //logged in, set to false to not be logged in 

ControllerContext controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller); 
controller.ControllerContext = controllerContext; 

這是冗長設置的一點點,但一旦你有一切就緒,測試各種的條件變得更容易。

+0

完美。答案仍然相關。+ 1 – joshmcode 2016-11-02 21:22:25

7

這不是最簡單的事情,但它可以做到。 User屬性只是委託給Controller.HttpContext.User。兩者都是非虛擬的只讀屬性,所以你不能對它們做任何事情。但是,Controller.HttpContext委託給ControllerBase.ControllerContext,它是一個可寫屬性。

因此,在執行被測系統(SUT)之前,您可以將Test Double HttpContextBase分配給Controller.ControllerContext。使用Moq,它看起來像這樣:

var user = new GenericPrincipal(new GenericIdentity(string.Empty), null); 
var httpCtxStub = new Mock<HttpContextBase>(); 
httpCtxStub.SetupGet(ctx => ctx.User).Returns(user); 

var controllerCtx = new ControllerContext(); 
controllerCtx.HttpContext = httpCtxStub.Object; 

sut.ControllerContext = controllerCtx; 

然後調用您的操作並驗證返回結果是否爲RedirectResult。

此測試利用了隱式知識,當您使用空名稱創建GenericIdentity時,它將爲IsAuthenticated返回false。您可以考慮通過使用Mock<IIdentity>來更明確地進行測試。

相關問題