我避免耦合和促进可重用性的方法是:
1.) 按实体对我的步骤进行分组,例如 AccountRepositorySteps(用于 AccountRepository)或 AccountControllerSteps(用于 AccountController)。
2.) 使步骤依赖于抽象,而不是具体(就像我们对生产代码所做的那样)。
3.) 依靠当前的 ScenarioContext 在步骤和步骤文件之间传递值。
这是一个简短的示例:
Given a guy with the name Darren exists
And a guy with the name John exists
When I hit the guy page
Then I should see two guys
存储库步骤.cs
private List<string> guys;
[BeforeScenario]
public void Setup(){
guys = new List<string>();
var fake = new Mock<IRepository>();
fake.Setup(x=>x.GetGuys()).Returns(guys);
ScenarioContext.Current.Set(fake) // Mock<IRepository>
ScenarioContext.Current.Set(fake.Object); // IRepository
}
[Given("a guy with the name '(.*)' exists"]
public void a(string guy){
guys.Add(guy);
// and if I need to pull out the mock, I can do it like so
var fake = ScenarioContext.Current.Get<Mock<IRepository>>();
}
GuyController.cs
When["I hit the guy page"]
public void x(){
var repository = ScenarioContext.Current.Get<IRepository>();
var controller = new GuyController(repository);
var result = controller.Index();
ScenarioContext.Current.Set(result);
}
看,这里 GuyController 的步骤获取了那个模拟对象,但他不知道它是一个模拟对象。对他来说,这只是一个 IRepository。如果由于某种原因,您需要为 IRepository 加载 REAL 存储库并想要运行您的规范,那么您所要做的就是使用真实的 IRepository 加载 ScenarioContext。
遵循这种模式,我的步骤非常分离,并且不受我对他人所做的更改的影响。它比我早期使用 SpecFlow 时使用的技巧要好得多,我会在同一个步骤文件中使用静态方法或将不相关的步骤分组。