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

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

お役に立てれば。

于 2012-11-20T13:06:16.947 に答える
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);

}
于 2012-11-20T10:26:37.583 に答える