asp.net-mvc - 使用 Moq 模拟 HttpContextBase

标签 asp.net-mvc moq

我有一个单元测试装置,我试图在 ASP.NET MVC Controller 上测试 ControllerAction,该 Controller 用于 Web 应用程序上的成员函数。我正在尝试模拟 HttpContext 进行测试。测试中的 ControllerAction 实际上在 HttpContext 上设置属性,例如 Session 值、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 对象,以便我的 Controller 实际上可以在其属性上设置值,我会很高兴我可以对这些属性进行断言,以确保我的 ControllerAction 正在执行我需要的操作。

我处理这个问题的方式是错误的吗?我知道 MVC Controller 有一个 ControllerContext,我可以用它来设置 Session 等的值,但我无法弄清楚如何在不注入(inject)它的情况下模拟类似的东西。有什么办法可以代替吗? (我还需要能够将上下文传递给我的 MembershipProvider)这是更好的方法吗?

谢谢。

最佳答案

我正在使用 Steve Sanderson 的 Pro Asp.NET MVC book 中包含的一些代码的版本...我目前面临道德困境,是否可以在此处发布代码。我是否可以妥协于高度精简的版本? ;)

因此,这可以很容易地重用,创建一个类似于下面的类,您将传递给 Controller ​​。这将设置您的模拟并将它们设置到 Controller 的 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 实例并传入您正在测试的 Controller 对象:

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

看起来与 Craig 的示例非常相似,但这是使用 Moq v3 的。我必须为此向 Steve Sanderson 表示支持 - 我使用它作为测试各种传统上难以测试的东西的基础:cookie、 session 、请求方法、查询字符串等等!

关于asp.net-mvc - 使用 Moq 模拟 HttpContextBase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1228179/

相关文章:

c# - 在遵循数据库优先方法时,使用 [NotMapped] 将附加信息传递给 View

javascript - MVC 无法使用某些 JS 库

C# Moq 如何获取所有方法调用

c# - 在存储库中模拟 DbSet<TEntity>

c# - 了解 Moq 的 Setup() 函数

c# - 如何在 Visual Studio 2013 上使用(Layout Razor)添加 MVC 5 View 页面

c# - 如何解决 Azure "Windows logins are not supported in this version of SQL Server"?

javascript - 有没有一种方法可以在不使用 ASP.NET MVC 的情况下呈现 CSS/Javascript 包?

c# - Membership.CreateUser 的 ASP.NET MVC 3 单元测试总是返回 MembershipCreateStatus 错误

mono - 如何停止modevelop 添加**-noconfig** 编译选项?