2009-11-23 13 views

Respuesta

14

He estado utilizando los siguientes Mocks con Moq para permitir configurar varias condiciones en las pruebas de mi unidad. En primer lugar, la maqueta 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; 
    } 

Cada propiedad que podrían proporcionar una Mock útil se estableció aquí. De esa manera, si tengo que añadir algo así como un referente, que sólo puede utilizar:

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

El método "GetPrincipleMock" es lo que establece el usuario. Se ve así:

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; 
    } 

Ahora, mis configuraciones de controlador en las pruebas de tener este aspecto:

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; 

Es un poco de configuración detallado, pero una vez que tenga todo en su lugar, poniendo a prueba una variedad de las condiciones se vuelve mucho más fácil.

+0

Perfecto. La respuesta sigue siendo relevante. + 1 – joshmcode

7

No es lo más simple de hacer, pero se puede hacer. La propiedad User simplemente delega a Controller.HttpContext.User. Ambas son propiedades de solo lectura no virtuales, por lo que no puede hacer nada al respecto. Sin embargo, Controller.HttpContext delega a ControllerBase.ControllerContext que es una propiedad de escritura.

Por lo tanto, puede asignar una prueba doble HttpContextBase a Controller.ControllerContext antes de ejercitar su sistema bajo prueba (SUT). El uso Moq, se vería algo como esto:

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; 

luego llamar a su acción y verificar que el resultado devuelto es un RedirectResult.

Esta prueba utiliza el conocimiento implícito de que cuando se crea una identidad genérica con un nombre vacío, devolverá falso para IsAuthenticated. Podría considerar hacer la prueba más explícita utilizando en su lugar un Mock<IIdentity>.

Cuestiones relacionadas