1

我有一个示例 ASP.NET MVC 3 Web 应用程序,它遵循 Jonathan McCracken 的 Test-Drive Asp.NET MVC(顺便说一句,很棒的书),我偶然发现了一个问题。请注意,我使用的是 MVCContrib、Rhino 和 NUnit。

    [Test]
    public void ShouldSetLoggedInUserToViewBag() {
        var todoController = new TodoController();
        var builder = new TestControllerBuilder();
        builder.InitializeController(todoController);

        builder.HttpContext.User = new GenericPrincipal(new GenericIdentity("John Doe"), null);

        Assert.That(todoController.Index().AssertViewRendered().ViewData["UserName"], Is.EqualTo("John Doe"));
    }

上面的代码总是抛出这个错误:

System.AccessViolationException : 试图读取或写入受保护的内存。这通常表明其他内存已损坏。

控制器动作代码如下:

[HttpGet]
    public ActionResult Index() {
        ViewData.Model = Todo.ThingsToBeDone;
        ViewBag.UserName = HttpContext.User.Identity.Name;

        return View();
    }

据我所知,由于控制器操作中的两个分配,该应用程序似乎崩溃了。但是,我看不出哪里有问题!?

谁能帮我找出解决这个问题的方法。

谢谢你。

编辑 1

我做了一些实验来看看问题是什么。删除ViewData,Model作业时,问题超越Expected result to be of type ViewResult. It is actually of type ViewResult.. 分配是如此基本,ViewData以至于我认为这不是问题,所以我认为 Rhino 或 MVCcontrib 与 MVC 3 结合使用有问题。

我还为相同的控制器操作编写了以下测试:

        [Test]
    public void ShouldDisplayAListOfTodoItems() {
        Assert.That(((ViewResult)new TodoController().Index()).ViewData.Model, Is.EqualTo(Todo.ThingsToBeDone));
    }

现在这个失败了,System.NullReferenceException : Object reference not set to an instance of an object可能是因为没有为这个特定的测试设置 HttpContext。删除ViewBag作业时,一切正常。

希望这能让问题更清楚。

编辑 2

在删除ViewData.Model赋值后调试代码时,它会抛出一个不同的错误:System.NullReferenceException : Object reference not set to an instance of an object.ViewBag赋值上。

4

2 回答 2

5

好吧,我已经把这个打倒了。正如我所怀疑的,这是因为 MVCContrib。请注意,我正在使用 MVCContrib 尚未正式支持的 MVC 3 Beta。考虑到这一点,我下载了 MVC 3 分支的最新 MVCContrib 源代码。

转到MVCContrib Sources,切换到mvc3分支,下载并使用附加的 bat 构建二进制文件。然后,将所需的文件包含到您的解决方案中。

好吧,这可能会在未来的稳定版本中得到修复,但我想它可能对其他人有用。感谢达林的关注。

于 2011-01-02T21:30:45.060 回答
1

这个怎么样:

[Test]
public void ShouldSetLoggedInUserToViewBag() 
{
    // arrange
    var todoController = new TodoController();
    var builder = new TestControllerBuilder();
    builder.InitializeController(todoController);

    builder.HttpContext
        .Stub(x => x.User)
        .Return(new GenericPrincipal(new GenericIdentity("John Doe"), null));

    // act
    var actual = todoController.Index();

    // assert
    actual.AssertViewRendered();
    Assert.That(todoController.ViewData["UserName"], Is.EqualTo("John Doe"));
}

和控制器动作:

[HttpGet]
public ActionResult Index() 
{
    ViewBag.UserName = HttpContext.User.Identity.Name;
    return View(Todo.ThingsToBeDone);
}

备注:我会将信息包含在视图模型中并避免使用ViewData/ViewBag. 它不是强类型的,它会强制您使用魔术引号。

于 2011-01-02T08:51:06.593 回答