我是第一次尝试 SpecFlow,我想知道我是否可能过度思考了整个概念,或者更糟糕的是,完全滥用它来达到预期目的?
我想为我的 WinForms 项目采用 MVP-VM 架构设计模式,并列出样板故事,以定义遵循相同模式的未来项目。
欢迎任何建议,谢谢!
Feature: DesignPattern
In order to encourage pluggability and loose coupling
As a software developer who has to comply with company GUI standards
I want to make sure the MVP-VM design pattern is enforced
@mytag
Scenario: MainPresenter loosely couples with IMainView and IModelContainer implementations
Given a stub of the IMainView interface
And a stub of the IModelContainer interface
When I create a new MainPresenter with the IMainView and IModelContainer stubs as arguments
Then the MainPresenter should have the IMainView and IModelContainer stubs as properties
Scenario: MainPresenter tightly couples with MainViewModel
Given a stub of the IMainView interface
And a stub of the IModelContainer interface
When I create a new MainPresenter with the IMainView and IModelContainer stubs as arguments
Then the MainPresenter should have a collection of MainViewModels as a property
Scenario: IModelContainer contains all required model interfaces
Given a stub of the IModelContainer interface
Then the IModelContainer stub should have an IContractsModel property
Scenario: IMainView extends the company BaseView GUI standard
Given a stub of the IMainView interface
Then the IMainView stub should extend the IBaseView interface
Scenario: IMainView exposes a datasource binding method that accepts a collection of MainViewModels as argument
Given a stub of the IMainView interface
And a collection of MainViewModels
Then the IMainView stub should have a BindViewModelsList method that accepts the collection of MainViewModels
Scenario: MainViewModel takes a ContractDataEntity and stores it as a property
Given a ContractDataEntity
When I create a new MainViewModel with the ContractDataEntity as argument
Then the MainViewModel should have the ContractDataEntity as a property
Scenario: MainViewModel presents the required attributes of its associated DataEntity
Given a ContractDataEntity
When I create a new MainViewModel with the ContractDataEntity as argument
Then the MainViewModel should have the ContractDataEntity ContractNumber as a property
And the MainViewModel should have the ContractDataEntity CustomerCode as a property
Scenario: MainViewModel has a factory method that translates a collection of DataEntities into MainViewModels
Given a collection of ContractDataEntities
When I call the MainViewModel TranslateDataEntityList factory method
Then it should return a collection on MainViewModels
然后,我将从 SpecFlow 方法生成类、属性和方法存根:
using Rhino.Mocks;
using Should.Fluent;
using TechTalk.SpecFlow;
namespace CONTR001.Test
{
[Binding]
public class DesignPatternSteps
{
[Given(@"a stub of the IMainView interface")]
public void GivenAStubOfTheIMainViewInterface()
{
IMainView view = MockRepository.GenerateStub<IMainView>();
ScenarioContext.Current.Set(view);
}
[Given(@"a stub of the IModelContainer interface")]
public void GivenAStubOfTheIModelContainerInterface()
{
IModelContainer model = MockRepository.GenerateStub<IModelContainer>();
ScenarioContext.Current.Set(model);
}
...
[When(@"I create a new MainPresenter with the IMainView and IModelContainer stubs as arguments")]
public void WhenICreateANewMainPresenterWithTheIMainViewAndIModelContainerStubsAsArguments()
{
var view = ScenarioContext.Current.Get<IMainView>();
var model = ScenarioContext.Current.Get<IModelContainer>();
var presenter = new MainPresenter(view, model);
ScenarioContext.Current.Set(presenter);
}
...
[Then(@"the MainPresenter should have the IMainView and IModelContainer stubs as properties")]
public void ThenTheMainPresenterShouldHaveTheIMainViewAndIModelContainerStubsAsProperties()
{
var presenter = ScenarioContext.Current.Get<MainPresenter>();
presenter.View.Should().Equal(ScenarioContext.Current.Get<IMainView>());
presenter.Model.Should().Equal(ScenarioContext.Current.Get<IModelContainer>());
}
...
[Then(@"the IMainView stub should extend the IBaseView interface")]
public void ThenTheIMainViewStubShouldExtendTheIBaseViewInterface()
{
var view = ScenarioContext.Current.Get<IMainView>();
view.Should().Be.AssignableFrom<IBaseView>();
}
}
}