Specflow 与 MVC 模型验证问题
在学习 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我必须将 AccountService 的连接字符串添加到 nunit 使用的 App.config 中。这导致 ValidatePasswordLengthAttribure 出现错误。
我已将检查正确错误消息的断言更新为:
仍然不确定 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:
Still unsure about whether the Membership.Provider is hitting the DB