3

シャープなアーキテクチャを使用しているため、単体テストや TDD でモックなどを簡単に使用できます。非常に複雑なビジネス ルールがあり、それらをコントローラー レベルでテストしたいと考えています。私は他の人がこれをどのように行うのか疑問に思っていますか?

私にとって、検証は 3 つのレベルでビジネス ルールをテストします。

(1) プロパティ レベル (例: プロパティは必須) (2) プロパティ内レベル (例: 開始日 < 終了日) (3) 永続性レベル (例: 名前は一意、親は子の子ではない)

私の検証フレームワークもプロパティにエラーを割り当てます。他の人はどうしているのだろう?ビジネス ルールごとにテストを作成し、正しいエラー メッセージが正しいプロパティに割り当てられているかどうかを確認しますか (つまり、ASP.MVC ModelState を調べますか)。

私の質問が理にかなっていることを願っています。どうもありがとう!

幸運をお祈りしています、

キリスト教徒

4

1 に答える 1

0

私は通常、これを 2 つに分割します。

  1. モデルが有効な場合とそうでない場合に、コントローラーが正しく動作するかどうかをテストします。
  2. ルール エンジンと組み合わせたモデルが正しいエラー メッセージを生成するかどうかをテストします。

論理的根拠は、コントローラーがエラーに対して正しく動作するかどうかに関係なく、モデル自体が正しく検証される場合、アプリケーションは正しく動作するということです。テストのセットアップも簡単になります。

投稿の最も単純なケースでは、すべてが正常な場合はコントローラーを結果ページにリダイレクトし、検証エラーが発生した場合は同じビューを再表示するようにします。

  [TestClass]
    public class Maintaining_todo_list
    {
        private TodoController controller;

        [TestInitialize]
        public void Setup()
        {
            controller = new TodoController {ControllerContext = new ControllerContext()};
        }

        [TestMethod]
        public void Valid_update_should_redirect_to_list()
        {
            var result = controller.Edit(1, new TodoItem {Text = "todo"});
            result.ShouldRedirectTo("list");
        }

        [TestMethod]
        public void Invalid_update_should_display_same_view()
        {
            var result = controller.Edit(1, new TodoItem {Text = ""});
            result.ShouldDisplayDefaultView();
        }
    }

モデルは、さまざまなメッセージでさまざまな方法で失敗する可能性があります。

   [TestClass]
    public class Validating_todo_item
    {
        [TestMethod]
        public void Text_cannot_be_empty()
        {
            var todo = new TodoItem {Text = ""};
            todo.ShouldContainValidationMessage("Text cannot be empty");
        }

        [TestMethod]
        public void Text_cannot_contain_more_than_50_characters()
        {
            var todo = new TodoItem { Text = new string('a', 51) };
            todo.ShouldContainValidationMessage("Text cannot contain more than 50 characters");
        }

        [TestMethod]
        public void Valid_items()
        {
            new TodoItem { Text = new string('a', 1) }.ShouldBeValid();
            new TodoItem { Text = new string('a', 50) }.ShouldBeValid();
        }
    }

(完全を期すために、ここにテスト ヘルパーを示します)

 internal static class AssertionHelpers
    {
        public static void ShouldRedirectTo(this ActionResult result, string action)
        {
            var redirect = result as RedirectToRouteResult;

            Assert.IsNotNull(redirect);
            Assert.AreEqual(action, redirect.RouteValues["action"]);
            Assert.IsNull(redirect.RouteValues["controller"]);
        }

        public static void ShouldDisplayDefaultView(this ActionResult result)
        {
            var view = result as ViewResult;

            Assert.IsNotNull(view);
            Assert.AreEqual("", view.ViewName);
        }

        public static void ShouldContainValidationMessage(this TodoItem todo, string message)
        {
            var context = new ValidationContext(todo, null, null);
            var results = new List<ValidationResult>();

            Validator.TryValidateObject(todo, context, results, true);

            var errors = results.Select(result => result.ErrorMessage);

            foreach (var error in errors)
            {
                Console.Out.WriteLine(error);
            }

            Assert.IsTrue(errors.Contains(message));
        }

        public static void ShouldBeValid(this TodoItem todo)
        {
            var context = new ValidationContext(todo, null, null);
            var results = new List<ValidationResult>();
            var isValid = Validator.TryValidateObject(todo, context, results, true);
            Assert.IsTrue(isValid);
        }
    }
于 2010-12-30T04:13:38.860 に答える