2016-08-23 65 views
4

我正在研究一種可以被認爲是另一種已經定義和測試過的方法的專門化方法。下面是一個例子代碼來說明:如何測試依賴於另一個已經測試過的方法的方法?

public class ProductService { 

    public void addProduct(Product product) { 
     //do something 
    } 

    public void addSpecialProduct(Product product) { 
     addProduct(product); 
     //do something after 
    } 

} 

我並不想複製我有addProduct這已經是相當複雜的測試。我想要的是當我爲addSpecialProduct定義測試時,我只需確保它在過程中也調用addProduct。如果這是兩類合作的問題,那麼很容易讓協作者嘲笑,並驗證目標方法被調用(並在必要時存根)。但是,這兩種方法屬於同一類。

我在想什麼,現在是來窺探我測試的對象,像:

public void testAddSpecialProduct() { 
    //set up code 
    ProductService service = spy(new DefaultProductService());  
    service.addSpecialProduct(specialProduct); 
    verify(service).addProduct(specialProduct); 
    //more tests 
} 

不過,我不知道這種做法是否以某種方式違背了單元測試的目的。關於這個問題的普遍共識是什麼?

+1

您可以在測試實用程序方法中爲您的'addProduct'方法聲明並在多個測試用例之間重複使用它嗎? – chrylis

+0

這個類聽起來有點代碼味道,將這2個功能(產品和特殊產品)組合成2個獨立的類(然後你的測試變得明顯和容易)會更好。具有通用的「添加」和「專業添加」可以擊敗單一責任。 – kuhajeyan

+0

@chrylis實際上聽起來很合理,是的。我忘記了我之前做過類似的事情。 –

回答

0

我認爲這取決於您希望如何使用單元測試。在極端意義上,單元測試只應該測試行爲,而不是實現。這意味着你需要複製你的測試(或者把@chrylis的建議提供給助手抽象出常用的功能)。確保調用其他方法是測試實現。

然而實際上,我認爲你對實例進行窺視以確保其他經過充分測試的方法被調用的想法是一個好主意。這是我的理由:

1)它簡化了你的代碼。

2)我立即清楚發生了什麼事情。它對我說,其他方法測試過的所有東西現在都是真實的,這裏是額外的斷言。

有一天,您可能會修改實現,以便不調用其他方法,這會導致您的單元測試失敗,這是人們通常不嘗試執行的嘗試避免的情況。但根據我的經驗,當行爲發生變化時,像這樣的變化更爲常見。

0

你可能會考慮重構你的代碼。使用戰略模式來實際實現添加產品和特殊產品的功能。

public class ProductService { 

    @Resource 
    private AddProductStrategy normalAddProductStrategy; 
    @Resource 
    private AddProductStrategy addSpecialProductStrategy; 

    public void addProduct(Product product) { 
     normalAddProductStrategy.addProduct(product); 
    } 

    public void addSpecialProduct(Product product) { 
     addSpecialProductStrategy.addProduct(product); 
    } 
} 

將會有AddProductStrategy的2個實現。其中一個就是在原來的ProductService.addProduct實現中發生了什麼。第二個實現將委託給第一個實現,然後完成所需的額外工作。因此,您可以分別測試每個策略。第二個策略實現僅僅是第一個實現的裝飾器。