我是否正确写入了我的第一个MSpec规格?

我正在写我的第一个MSpec规格,我想要一些指导。 我把规格留在了“待定”状态,但上下文已经填写完毕。 有什么改进吗?

作为参考,这是故事和第一个场景:

Story: "Blog admin logs in to the system" As a blog writer I want to be able to log in to my blog So that I can write posts and administer my blog Scenario: "Logs in from the login page" Given the user enters in correct credentials for a user in the system When the user clicks the "Login" button Then log the user in and redirect to the admin panel with a message stating that he logged in correctly 

并且MSpec代码(有些部分被剪切),注意到由于与Moq.It冲突,我必须将MSpec委托给别名。 It

 using MoqIt = Moq.It; using ThenIt = Machine.Specifications.It; [Subject("User tries logging in")] public class When_user_enters_valid_credentials : With_user_existing_in_membership { protected static ActionResult result; Because of = () => { result = loginController.Login(validUsername, validPassword); }; ThenIt should_log_the_user_in; ThenIt should_redirect_the_user_to_the_admin_panel; ThenIt should_show_message_confirming_successful_login; } public abstract class With_user_existing_in_membership { protected static Mock<ISiteMembership> membershipMock; protected static string validUsername; protected static string validPassword; protected static LoginController loginController; Establish context =()=> { membershipMock = new Mock<ISiteMembership>(); validUsername = "ValidUsername"; validPassword = "ValidPassword"; //make sure it's treated as valid usernames and password membershipMock .Setup<bool>(m => m.Validate( MoqIt.Is<string>(s => s == validUsername), MoqIt.Is<string>(s => s == validPassword))) .Returns(true); loginController = new LoginController(membershipMock.Object); }; } 

上下文看起来不错。 我喜欢你用别名解决冲突的方式。 我会争辩Moq别名可以改进。 考虑一下类似的句子。 例如, Param.Is<T>Value.Is<T>

一些笔记,用代码片断,然后整个规范重写在底部。

情景是你的Subject

主题可以是故事中的情景。 此外,它会与您的testing运行报告(特别是在HTML报告中很好)呈现。

 [Subject("Login Page")] 

不要把时间浪费在“With”命名的基类上

MSpec的创build者Aaron Jensen 已经完全恢复使用“With”语法。 上下文类名不会显示任何报告,所以避免浪费时间发明一个有意义的名字。

 public abstract class MembershipContext 

给定是你的规范类名称

在您的故事中的Given后面命名具体的spec类。 特别是由于基类名称没有报告任何地方,你可能会失去报告中的一半的上下文! 您还应该避免将testing系统的名称放在上下文类名中。 这使得您的上下文更友好,可以重构被测系统。

 public class When_an_existing_user_enters_valid_credentials 

基本规范类应该只包含一般的初始化

而且往往是不必要的。 导致安排和行动阶段分离。 使用基类进行通用字段初始化,例如设置模拟的依赖关系。 但是,你不应该嘲笑基类中的行为。 你不应该把特定于上下文的信息放在基类中。 在你的例子中,用户名/密码。 这样,您可以使用无效凭据创build第二个上下文。

 Establish context = () => { membership = new Mock<ISiteMembership>(); loginController = new LoginController(membership.Object); }; 

具体规范类中的字段应该是私有的

它减less了testing中的语言“仪式”。 您应该将它们放在所有MSpec特定代表的下方,因为规范的这些部分讲述了大部分故事。

 static ActionResult result; 

规范检修

这里的规范是一个很好的例子,build立一个全局上下文MembershipContext ,并在特定的上下文中inheritance它(因此,额外的Establish )。

 [Subject("Login Page")] public class When_an_existing_user_enters_valid_credentials : MembershipContext { Establish context = () => { membership .Setup<bool>(m => m.Validate( Param.Is<string>(s => s == username), Param.Is<string>(s => s == password))) .Returns(true); }; Because of = () => result = loginController.Login(username, password); It should_log_the_user_in; It should_redirect_the_user_to_the_admin_panel; It should_show_message_confirming_successful_login; static ActionResult result; const string username = "username"; const string password = "password"; } public abstract class MembershipContext { Establish context = () => { membership = new Mock<ISiteMembership>(); loginController = new LoginController(membership.Object); }; protected static Mock<ISiteMembership> membership; protected static LoginController loginController; }