2016-01-15 74 views
3

我上這是沒有考慮到測試寫的,並且不使用Spring遺留的Tomcat Web服務建立第一單元測試工作。我遇到的一個類是一個擴展HttpServlet的servlet。這是該課程的縮寫版本。如何在沒有(非默認)構造函數的Java類中模擬對象?

public class ItemServlet extends HttpServlet { 
    private ObjectMapper mapper; 
    private IItemDAO dao; 

    @Override 
    public void init() { 
     mapper = new ObjectMapper(); 
     dao = new GenericItemDao(...); 
    } 
} 

通常我會通過外部依賴關係的構造,但servlet被通過Tomcat的基礎上,web.xml配置,其只調用默認的構造函數和參數少init()方法創建的。因此,似乎沒有任何方法可以進行依賴注入來允許我在單元測試中進行模擬。我能想到的唯一方法就是創建一個只用於構造函數的構造函數,我可以使用它來實例化單元測試中的類,並將init()方法留給實際應用程序調用。我還可以創建第三個方法,可以雙方構造函數被調用,init()像這樣:

public class ItemServlet extends HttpServlet { 
    private ObjectMapper mapper; 
    private IItemDAO dao; 

    public ItemServlet(ObjectMapper mapper, IItemDAO dao) { 
     initDependencies(mapper, dao); 
    } 

    private void initDependencies(ObjectMapper mapper, IItemDAO dao) { 
     this.mapper = mapper; 
     this.dao = dao; 
    } 

    @Override 
    public void init() { 
     initDependencies(new ObjectMapper(), new GenericItemDAO(...)); 
    } 
} 

有沒有單元測試這些類一個更清潔的方式?

+1

如果你可以使用[PowerMockito(https://github.com/jayway/powermock/wiki/MockConstructor)框架,你可以嘲笑ObjectMapper'的'的構造函數和'ItemDAO'類。參見實施例[這裏](https://stackoverflow.com/questions/26001713/how-do-you-mock-classes-that-are-used-in-a-service-that-youre-trying-to-unit- TE/26054804#26054804)。希望這可以幫助 – troig

回答

3

我想利用這個機會來解耦代碼並使其可測試。事實上,如果你正在代表Tomcat實例化一個servlet,只是爲了檢查它的一個方法是否會返回一個期望值,那麼你就沒有辦法進行單元測試,而是在進行集成測試。

使用mock框架來解決,這將投目前執行的石頭,並使其不可能改變的 - 除非這些變化以及變化的測試去。

我的單元測試的絕對擁護者,我也是一個實用主義者做什麼是可能的情況下,我的幾個框架層,使其難以測試中發現自己。在這種情況下,(我只知道你的servlet的依賴,沒有任何其他的 - 你會知道你在哪裏),我喜歡我的代碼沒有框架依賴分成

  • 原子,單位可測試單位
  • 佈線代碼,將可測試代碼與框架連接起來。

接線代碼自然不是很複雜,並且沒有得到任何測試(由於大量的依賴關係)。它雖然獲得同行評審。

+1

我並沒有真正測試任何servlet功能,但實際上是方法內的業務邏輯(doPost,doGet等)。然而,如果我將所有實際的邏輯委託給另一個類(比如ItemRequestHandler),那麼我可以完全單元測試它,並且只保留骨架servlet類未經測試。這正是我在另一個項目(NodeJS)中使用的技術,我認爲這是一條路。 – Jared

2

您可以將getters/setters添加到課程中,並通過那裏將mocks注入課程中。