你真正想要测试的是最终结果。例如,您可能希望确保在模型状态无效时返回正确的 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 (只是为了我的方便),但你明白了。
希望这可以帮助。