我写了一个单元测试
// 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();
}
答案 0 :(得分:1)
是的,它会因为ModelState上的错误而失败,因此您可以比较操作方法的结果类型,检查modelState并检查模型。我建议测试一下这样的代码:
[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);
}
答案 1 :(得分: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(仅为方便起见),但你明白了。
希望这有帮助。