1

我写了一个单元测试

// Arrange                    
FocusController controller = new FocusController();
controller.ModelState.AddModelError("", "mock error message");
// Act

FocusFormModel focus = new FocusFormModel();
focus.FocusName = "Mock Focus";
focus.Description = "Mock Description";
focus.GroupId = 1;
var result = controller.CreateFocus(focus) as RedirectToRouteResult;
//// Assert 

Assert.That(result, Is.Not.Null);

此处单元测试失败,因为模型状态无效。

我的控制器动作是:

[HttpPost]
public ActionResult CreateFocus(FocusFormModel focus)
{ 
    if (ModelState.IsValid)
    {
        var createdfocus = focusService.GetFocus(focus.FocusName);
        return RedirectToAction("Focus", new { id = createdfocus.FocusId });
    }

    return View("CreateFocus",focus);
}

我的索引操作:

Public ActionResult Index(int id)
{
    return View();
}
4

2 回答 2

1

Yes, it will fail because you have an error on the ModelState, so you could compare the result type of your action method, check the modelState and check the model as well. I recommend test doing a code like this:

[TestMethod]
public void Should_have_return_an_error()
{
    FocusController controller = new FocusController();

    // you add this value on ModelState to force the error
    controller.ModelState.AddModelError("", "mock error message");

    // Act
    FocusFormModel focus = new FocusFormModel();
    focus.FocusName = "Mock Focus";
    focus.Description = "Mock Description";
    focus.GroupId = 1;

    const string viewNameResult = "Index"; //or whatever your action tested should return

    // it will return the error
    var result = controller.CreateFocus(focus) as ViewResult;


    //// Assert the Action type result...
    Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));

    //// Assert the model..
    Assert.AreEqual(focus, result.Model);

    //// Aseert the ModelState
    Assert.IsFalse(result.ModelState.IsValid);

    Assert.AreEquals(result.ViewName, viewNameResult);

}
于 2012-11-20T10:26:37.583 回答
1

你真正想要测试的是最终结果。例如,您可能希望确保在模型状态无效时返回正确的 ViewName。你只会测试一件事。

如果您以 TDD 方式执行此操作...

从失败的测试开始。如果模型状态无效,我只关心预期结果。如果模型状态无效,我希望返回特定视图。

单元测试:

   [TestMethod]
    public void CreateFocus_WhenModelStateIsNotValid_ReturnsViewNameCreateFocus()
    {
       // Arrange                    
        var stubFocusService = new Mock<IFocusService>();
        var controller = new FocusController(stubFocusService.Object);
        controller.ModelState.AddModelError("", "fake error message");
        const string expectedViewNameWhenModelError = "CreateFocus";

        // Act
        var result = controller.CreateFocus(It.IsAny<FocusFormModel>()) as ViewResult;

        // Assert 
        Assert.AreEqual(expectedViewNameWhenModelError, result.ViewName);
    }

被测系统:

    [HttpPost]
    public ActionResult CreateFocus(FocusFormModel focus)
    {
        return new EmptyResult();
    }

现在编写足够的生产代码以使测试通过

    [HttpPost]
    public ActionResult CreateFocus(FocusFormModel focus)
    {
        if (!ModelState.IsValid)
        {
            return View("CreateFocus", focus);
        }

         return new EmptyResult();
    }

测试通过。我们还没有完成。如果模型状态有效,我们还想测试我们得到预期的视图。我们为此编写了一个不同的测试。

从失败的测试开始

   [TestMethod]
    public void CreateFocus_WhenModelStateIsValid_EnsureRouteNameFocus()
    {
        // Arrange                    
        var stubFocusService = new Mock<IFocusService>();
        stubFocusService.Setup(x => x.GetFocus(It.IsAny<string>())).Returns(new Focus());
        var controller = new FocusController(stubFocusService.Object);
        const string expectedRouteNameWhenNoModelError = "Focus";

        // Act
        var result = controller.CreateFocus(new FocusFormModel()) as RedirectToRouteResult;

        // Assert 
        Assert.AreEqual(expectedRouteNameWhenNoModelError, result.RouteValues["action"]);
    }

我们重构生产代码以使测试通过。再次绝对必要的..

    [HttpPost]
    public ActionResult CreateFocus(FocusFormModel focus)
    {
        if (!ModelState.IsValid)
        {
            return View("CreateFocus", focus);
        }

        var createdfocus = _focusService.GetFocus(focus.FocusName);
        return RedirectToAction("Focus", new { id = createdfocus.FocusId });
    }

现在运行所有测试并确保它们都通过。重构您的测试以删除任何重复。

请注意,您可能使用 NUnit 或其他,但我使用 MSTest 进行了演示。我会使用手写存根,但在 Moq 中模拟很简单。我还将 Model.IsValid 切换为 !Model.IsValid (只是为了我的方便),但你明白了。

希望这可以帮助。

于 2012-11-20T13:06:16.947 回答