开发者

Specflow with MVC Model Validation Issue

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 = "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);
        }

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开发者_JS百科
  • 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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜