Specflow 与 MVC 模型验证问题

发布于 2024-11-09 21:20:22 字数 3725 浏览 4 评论 0原文

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

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

步骤

[Given(@"The user has not entered the username")]
        public void GivenTheUserHasNotEnteredTheUsername()
        {   
            _registerModel = new RegisterModel
            {
                UserName = null,
                Email = "[email protected]",
                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 = "[email protected]",
                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));

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

有什么想法吗?

功能

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

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

  • 鉴于用户尚未输入 密码
  • 当他单击“注册”按钮
  • 时,应该向他显示错误消息“‘密码’必须至少为 6 个字符长。”“密码”

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

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

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

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

谢谢。

I am using Specflow, nunit and moq to test the default MVC2 application registration as I learn SpecFlow.

I have the following steps for checking if the username and password have not been entered.

Steps

[Given(@"The user has not entered the username")]
        public void GivenTheUserHasNotEnteredTheUsername()
        {   
            _registerModel = new RegisterModel
            {
                UserName = null,
                Email = "[email protected]",
                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 = "[email protected]",
                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);
        }

Extension method to force validation

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 });
        }
    }`

I do not understand why the password missing test fails on the following lines.

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

I have noticed that the error message being returned is for the Password and ConfirmPassword not matching but I dont understand why for all the other tests, including the Missing Confirm Password test (Identical to the missing Password test) they work fine.

Any ideas?

Features

  • Scenario: Register should return error if username is missing
  • Given The user has not entered the username
  • When He Clicks on Register button
  • Then He should be shown the error
    message "The Username field is required." "username"

  • Scenario: Register should return error if password is missing

  • Given The user has not entered the
    password
  • When He Clicks on Register button
  • Then He should be shown the error message "'Password' must be at least
    6 characters long." "Password"

UPDATE
Ok seems the ValidatePasswordLengthAttribute in the Account Model couldn't initilise Membership.Provider as I did not have the connectionstring in my app.config. Is the Pembership.Provider connecting to the membership DB now?

I have added the connection string but now the test passes 50% of the time as it returns two errors:

  • Password required
  • Password must be 6 chars long.

The problem is that they are not returned in the same order every time so the test is flaky.
How can I rewrite my scenario and test to account for this? Can I still keep the one "Then" method or do I need to create a new method?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

川水往事 2024-11-16 21:20:22

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

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

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

仍然不确定 Membership.Provider 是否正在访问数据库

I had to add the connection string the the AccountService to the App.config which nunit uses. This was causing an error on the ValidatePasswordLengthAttribure.

I have updated the Assert which checks for the correct error message to:

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

Still unsure about whether the Membership.Provider is hitting the DB

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文