我具有其中我试图向被用于隶属函数上的web应用程序的ASP.NET MVC控制器上测试一个ControllerAction一个单元测试夹具。我想嘲笑为测试的HttpContext。被测ControllerAction实际上是设置在HttpContext的属性,如会话值,Response.Cookies值等,这是不是所有的代码,但在这里就是我试图去运行测试的粗略样本:

[Test]
public void ValidRegistrationDataSuccessfullyCreatesAndRegistersUser()
{
    var context = new Mock<HttpContextBase>() {DefaultValue = DefaultValue.Mock};
    context.SetupAllProperties();
    var provider = new Mock<MembershipProvider>(new object[] {context.Object});
    var controller = new AccountController(context.Object, provider.Object);
    // This just sets up a local FormCollection object with valid user data 
    // in it to use to attempt the registration
    InitializeValidFormData();
    ActionResult result = controller.Register(_registrationData);
    Assert.IsInstanceOfType(typeof(ViewResult), result);
    // Here is where I'd like to attempt to do Assertions against properties 
    // of the HttpContext, like ensuring that a Session object called "User" 
    // exists, and new auth cookie exists on the Response.Cookies collection. 
    // So far I've been unable to successfully check the values of those properties.
    // I've been unsuccessful in getting those properties setup correctly on my 
    // mock object so that my ControllerAction can actually *set* their values, 
    // and that I can make assertions on them afterwards. The above code actually
    // generates a StackOverflowException (which I've reported) on the
    // context.SetupAllProperties() call. What am I doing wrong, or what do I need 
    // to do to be able to set and assert on those context properties?
}

不知道我做错了,但我喜欢它,如果有人可以点我在正确的方向,并告诉我如何设置,使得我的控制器实际上可以在其属性设置的值此模拟HttpContextBase对象,我可以对这些属性的断言,以确保我的ControllerAction是做什么我需要它。

难道我处理这个错误的方式?我知道MVC控制器有一个ControllerContext,我可以用它来进行会话等设定值,但我无法弄清楚如何这样的事情可能没有将其注入被嘲笑。有没有这样做,而不是某种方式? (我还需要能够通过上下文到我的MembershipProvider太)那会是一个更好的方法吗?

感谢。

有帮助吗?

解决方案

我使用一个版本的一些代码史蒂夫·桑德森包括在他的临Asp.NET MVC书 ......和我目前有一个道德困境是否也没关系张贴在这里的代码。怎么样我一个高度精简版妥协? ;)

因此,这可以很容易地被重用,创建类似如下的一个,你会通过你的控制器类。这将设置你的嘲弄,并将其设置为您控制器的ControllerContext

public class ContextMocks
{
    public Moq.Mock<HttpContextBase> HttpContext { get; set; }
    public Moq.Mock<HttpRequestBase> Request { get; set; }
    public RouteData RouteData { get; set; }

    public ContextMocks(Controller controller)
    {
        //define context objects
        HttpContext = new Moq.Mock<HttpContextBase>();
        HttpContext.Setup(x => x.Request).Returns(Request.Object);
        //you would setup Response, Session, etc similarly with either mocks or fakes

        //apply context to controller
        RequestContext rc = new RequestContext(HttpContext.Object, new RouteData());
        controller.ControllerContext = new ControllerContext(rc, controller);
    }
}

然后在您的测试方法,你只是创建ContextMocks的实例,并通过在你正在测试的控制器对象:

[Test]
Public void test()
{
     var mocks = new ContextMocks(controller);
     var req = controller.Request; 
     //do some asserts on Request object
}

似乎非常类似于Craig的例子,但这是与起订量V3。我必须给道具史蒂夫·桑德森这个 - 我用这个作为一个基础测试各种否则传统上难以测试的东西:Cookie,会话,请求方法,查询字符串和多个

其他提示

这里是我如何做到这一点

    public static HttpContextBase FakeHttpContext()
    {
        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 user = new Mock<IPrincipal>();
        var identity = new Mock<IIdentity>();

        request.Expect(req => req.ApplicationPath).Returns("~/");
        request.Expect(req => req.AppRelativeCurrentExecutionFilePath).Returns("~/");
        request.Expect(req => req.PathInfo).Returns(string.Empty);
        response.Expect(res => res.ApplyAppPathModifier(It.IsAny<string>()))
            .Returns((string virtualPath) => virtualPath);
        user.Expect(usr => usr.Identity).Returns(identity.Object);
        identity.ExpectGet(ident => ident.IsAuthenticated).Returns(true);

        context.Expect(ctx => ctx.Request).Returns(request.Object);
        context.Expect(ctx => ctx.Response).Returns(response.Object);
        context.Expect(ctx => ctx.Session).Returns(session.Object);
        context.Expect(ctx => ctx.Server).Returns(server.Object);
        context.Expect(ctx => ctx.User).Returns(user.Object);

        return context.Object;
    }

这是通过斯科特汉塞尔尔曼释放的MvcMockHelpers库。这是Moq的2.0代码;语法是在3稍有不同。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top