2011-01-05 2 views
3

내 애플 리케이션을 지정하는 specflow를 사용하고, 정말 나쁜 물건을 수행하지 않도록 나를 저장했습니다 :-) 그러나 단계 사이의 커플 링에 문제가 있습니다 : 예를 들어 내가 한 단계에서 무언가를 무겁게 사용하고 있기 때문에 모의에 엔티티를 반환해야한다고 말하고 있지만 다른 엔 모의에게 동일한 엔티티를 반환 하겠지만 다른 속성으로 보냅니다.작은 오이 사양의 단계 사이에 강력한 커플

이 단계에서 봐 (아래 Darrens 대답에서 도난 및 수정) :

Given a guy the following guy exists: 
| Name  | Age | Salary | 
| John Doe | 42 | 400 | 
When his salary changes to 420 
And I run the paycheck program 
Then he should be paid 420 

을 나는 녀석 객체로 시작하고 나중에 객체 수정 여기를 참조하십시오 - 내가 테스트하고있는 것입니다.

그래서 모의 저장소에 개체를 넣은 다음 다른 단계에서 개체를 꺼내어 다시 넣습니다. 단계 간의 높은 결합 및 재사용 가능성을 어떻게 피할 수 있습니까?

물론 시나리오 클래스에 로컬 변수를 유지하고 해당 엔터티를 모든 변수에 넣을 수는 있지만 단계를 연결해야합니다.) AccountRepository에 대한 AccountRepositorySteps() 또는 AccountControllerSteps 같은 (AccountController를 들어, 엔티티에 의해

1) 그룹 내 단계 : 나는 커플 링을 방지하고 재사용 성을 증진

답변

6

방법은이다.

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 

RepositorySteps.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를 사용하면서 초기 단계에서 사용한 트릭보다 훨씬 효과적입니다. 정적 방법을 사용하거나 관련없는 단계를 같은 단계 파일에 그룹화합니다.

0

동작을 분할하는 것이 더 나은지 궁금합니다.

Scenario: Change Salary 

Given a guy the following guy exists: 
| Name  | Age | Salary | 
| John Doe | 42 | 400 | 
When his salary changes to 420 
Then his salary should be 420 

그리고 ...

Scenario: Pay Guy 

Given a guy the following guy exists: 
| Name  | Age | Salary | 
| John Doe | 42 | 400 | 
And I run the paycheck program 
Then he should be paid 400 

그들은 행동의 별도의 단위입니다.

공유 된 컨텍스트와 관련하여 내가 간략한 해결책은 종속성 주입입니다. SharedContext 클래스를 만들어 공유 컨텍스트가 필요한 단계 정의 클래스에 삽입하십시오.그런 식으로 원하는대로 단계 정의 파일을 분할 할 수 있으며 컨텍스트를 공유 할 수 있습니다. 많은 도구들이 간단한 IoC 컨테이너 기능을 즉시 사용할 수 있습니다 (예 : SpecFlow).

class SharedContext 
{ 
object MyObject1 {get; set;} 
object MyObject2 {get; set;} 
//Etc. 
} 

class StepDefinitions1 
{ 

private SharedContext _context; 

public Stepdefinitions1(SharedContext context) 
{ 
this._context = context; 
}  
//Now use this._context.Properties to get at the shared objects in your 
//step definitions  
} 

컨테이너가 나머지 부분을 처리합니다.

SharedContext 클래스의 개체 수명주기는 단일 시나리오입니다. 나는. 각각의 새로운 시나리오에 대해 새로운 SharedContext가 생성되고 최종 "Then"단계가 실행될 때까지이를 참조하는 클래스의 모든 단계에 생성자를 통해 전달됩니다.

+0

그리고 oops! 이전 게시물. –

관련 문제