2012-02-03 123 views
0

我有一個測試方法。在其調用堆棧中,它調用一個實例使用JDBC與數據庫聊天的DAO。我對於瞭解JDBC層會發生什麼並不感興趣,我已經爲此做了測試,而且他們的工作非常出色。模擬方法沒有直接調用JMock的單元測試

我想模擬,使用JMock,DAO層,所以我可以專注於測試下的這個方法的細節。這是我所擁有的基本表現形式。

@Test  
public void myTest() 
{ 
    context.checking(new Expectations() { 
      { 
       allowing(myDAO).getSet(with(any(Integer.class))); 
       will(returnValue(new HashSet<String>())); 
      } 
    }); 

    // Used only to show the mock is working but not really part of this test. 
    // These asserts pass. 
    Set<String> temp = myDAO.getSet(Integer.valueOf(12)); 
    Assert.assertNotNull(temp); 
    Assert.assertTrue(temp.isEmpty()); 

    MyTestObject underTest = new MyTestObject(); 
    // Deep in this call MyDAO is initialized and getSet() is called. 
    // The mock is failing to return the Set as desired. getSet() is run as 
    // normal and throws a NPE since JDBC is not (intentionally) setup. I want 
    // getSet() to just return an empty set at this layer. 
    underTest.thisTestMethod(); 
    ... 
    // Other assertions that would be helpful for this test if mocking 
    // was working. 
} 

它,從我已經學會了創造這個測試,我可以不使用JMock的嘲笑間接對象。或者我沒有看到一個關鍵點。我希望下半場是真實的。

想法和謝謝。

回答

0

從這段代碼中,我猜測MyTestObject使用反射或靜態方法或字段來獲取DAO,因爲它沒有構造函數參數。 JMock不會按類型替換對象(現在任何時候,都會有一羣人推薦其他框架)。

這是故意的。 JMock的一個目標是突出對象設計的弱點,要求清潔依賴和集中行爲。我發現在域對象中嵌入DAO/JDBC訪問最終會讓我陷入困境。這意味着域對象具有祕密依賴性,這使得它們更難理解和改變。我更願意在代碼中明確地表達這些關係。

所以你必須將模擬對象以某種方式放入目標代碼中。如果你不能或不想這樣做,那麼你將不得不使用另一個框架。

P.S.的風格一點,你可以簡化這個測了一下:

context.checking(new Expectations() {{ 
    allowing(myDAO).getSet(12); will(returnValue(new HashSet<String>())); 
}}); 

測試中,你應該知道什麼是價值期待和飼料到這一點的期望。這使得更容易看到對象之間的值的流動。

+0

在setUp()中,我使用context.mock(MyDAO.class)來模擬myDAO。在MyTestObject的互操作中,MyDAO被實例化爲'new'。 – DDus 2012-02-07 16:02:24

+0

那就是這個問題。你有一個我們看不到的隱式依賴。您現在必須決定是否要明確依賴或者使用其中一個更聰明的框架進行干預。我想你可以猜出哪一個我更喜歡:) – 2012-02-21 09:37:30

+0

我們用JMockit代替,但也考慮添加PowerMock的選項。 – DDus 2012-02-21 14:36:58