3

我正在使用清晰的架构,因此我可以在单元测试和/或 TDD 期间轻松使用模拟等。我有相当复杂的业务规则,想在控制器级别测试它们。我只是想知道其他人如何做到这一点?

对我来说,验证测试三个级别的业务规则:

(1) 属性级别(例如需要属性) (2) 内部属性级别(例如开始日期 < 结束日期) (3) 持久级别(例如名称是唯一的,父级不能是子级的子级)

我的验证框架还将错误分配给属性。我只是想知道其他人是做什么的?您是否为每个业务规则编写测试并检查是否将正确的错误消息分配给正确的属性(即查看 ASP.MVC 模型状态)?

我希望我的问题是有道理的。非常感谢!

最良好的祝愿,

基督教

4

1 回答 1

0

我通常把它分成两部分:

  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 回答