2011-01-05 36 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 

看到這裏我開始和一個男生對象,後來修改的對象 - 這是我測試的東西。

因此,我把一個實體放到模擬庫中,然後在另一個步驟中將其拉出並重新放入。 如何避免步驟之間的高耦合和可重用性?

當然,我可以在場景類中保留一個局部變量,並將所有實體放在該變量中,但是然後我會耦合這些步驟。

回答

6

我避免耦合和促進再使用性的方法是:

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 

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存儲庫並想運行您的規格,那麼您只需將ScenarioContext加載到真正的IRepository中即可。

按照這種模式,我的步驟是非常脫鉤,並保護我免受其他人的變化。它比我在使用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

哎呀!舊帖子。 – 2012-09-27 11:17:48