0

在学习 SpecFlow 时,我正在使用 Specflow、nunit 和 moq 来测试默认的 MVC2 应用程序注册。

我有以下步骤来检查是否没有输入用户名和密码。

脚步

[Given(@"The user has not entered the username")]
        public void GivenTheUserHasNotEnteredTheUsername()
        {   
            _registerModel = new RegisterModel
            {
                UserName = null,
                Email = "test@dummy.com",
                Password = "test123",
                ConfirmPassword = "test123"
            };      
        }

[Given(@"The user has not entered the password")]
        public void GivenTheUserHasNotEnteredThePassword()
        {
            _registerModel = new RegisterModel
            {
                UserName = "user" + new Random(1000).NextDouble().ToString(),
                Email = "test@dummy.com",
                Password = string.Empty,
                ConfirmPassword = "test123"
            };  
        }

[When(@"He Clicks on Register button")]
        public void WhenHeClicksOnRegisterButton ()
        {
            _controller.ValidateModel(_registerModel);
            _result = _controller.Register(_registerModel);
        }

[Then(@"He should be shown the error message ""(.*)""  ""(.*)""")]
        public void ThenHeShouldBeShownTheErrorMessage(string errorMessage, string field)
        {
            Assert.IsInstanceOf<ViewResult>(_result);
            var view = _result as ViewResult;
            Assert.IsNotNull(view);
            Assert.IsFalse(_controller.ModelState.IsValid);
            Assert.IsFalse(view.ViewData.ModelState.IsValidField(field));
            Assert.IsTrue(_controller.ViewData.ModelState.ContainsKey(field));          

            Assert.AreEqual(errorMessage,
            _controller.ModelState[field].Errors[0].ErrorMessage);
        }

强制验证的扩展方法

public static class Extensions
    {
        public static void ValidateModel<T> ( this Controller controller, T modelObject )
        {
            if (controller.ControllerContext == null)
                controller.ControllerContext = new ControllerContext();

            Type type = controller.GetType();
            MethodInfo tryValidateModelMethod =
                type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(
                    mi => mi.Name == "TryValidateModel" && mi.GetParameters().Count() == 1).First();

            tryValidateModelMethod.Invoke(controller, new object[] { modelObject });
        }
    }`

我不明白为什么密码丢失测试在以下几行中失败。

    Assert.IsFalse(view.ViewData.ModelState.IsValidField(field));
    Assert.IsTrue(_controller.ViewData.ModelState.ContainsKey(field));

我注意到返回的错误消息是密码和 ConfirmPassword 不匹配,但我不明白为什么所有其他测试,包括 Missing Confirm Password 测试(与 Missing Password 测试相同)它们工作正常。

有任何想法吗?

特征

  • 场景:如果用户名丢失,注册应该返回错误
  • 给定用户尚未输入用户名
  • 当他点击注册按钮时
  • 然后应该向他显示错误消息“用户名字段是必需的”。“用户名”

  • 场景:如果密码丢失,注册应该返回错误

  • 给定用户尚未输入密码
  • 当他点击注册按钮时
  • 然后应该向他显示错误消息“'密码'必须至少有 6 个字符长。” “密码”

更新 好的,帐户模型中的 ValidatePasswordLengthAttribute 似乎无法初始化Membership.Provider,因为我的 app.config 中没有连接字符串。Pembership.Provider 现在是否连接到会员数据库?

我添加了连接字符串,但现在测试通过了 50% 的时间,因为它返回两个错误:

  • 需要密码
  • 密码长度必须为 6 个字符。

问题是它们不是每次都以相同的顺序返回,所以测试很不稳定。我该如何重写我的场景和测试来解决这个问题?我仍然可以保留一个“Then”方法还是需要创建一个新方法?

谢谢。

4

1 回答 1

0

我必须将 AccountService 的连接字符串添加到 nunit 使用的 App.config 中。这导致 ValidatePasswordLengthAttribure 出现错误。

我已将检查正确错误消息的 Assert 更新为:

Assert.AreEqual(errorMessage, 
            _controller.ModelState[field].Errors.First(e => e.ErrorMessage == errorMessage).ErrorMessage);

仍然不确定 Membership.Provider 是否击中数据库

于 2011-05-26T16:57:11.470 回答