本当にテストしたいのは、最終結果です。たとえば、モデルの状態が無効な場合に正しい ViewName が返されるようにしたい場合があります。1 つのことだけをテストします。
これを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 に切り替えました (便宜上) が、おわかりいただけると思います。
お役に立てれば。