2013-06-25 43 views
0

我想測試一個私有方法的行爲。 「moveDataToArchive」方法執行4個步驟。JMockit - 嚴格的期望被忽略

它是4x:計算日期+調用子方法。

這是我的測試:

@Test 
    public void testMoveData2Archive() throws Exception{ 

    final long now = 123456789000L; 

    //Necessary to make the archivingBean runable. 
    Vector<LogEntry> logCollector = new Vector<LogEntry>(); 
    Deencapsulation.setField(archivingBean, "logCollector", logCollector); 

    new NonStrictExpectations(archivingBean) { 
     {  //Lets fake the DB stuff. 
      invoke(archivingBean, "getConnection");result = connection; 
      connection.prepareStatement(anyString); result = prepStatement; 
      prepStatement.executeUpdate(); returns(Integer.valueOf(3), Integer.valueOf(0), Integer.valueOf(3)); 
     } 
    }; 

    new NonStrictExpectations(props) { 
     { //This is important. The numbers will be used for one of each 4 submethods 
      props.getProperty(ArchivingHandlerBean.ARCHIVING_CREDMATURITY_OVER_IN_DAYS); result = "160"; 
      props.getProperty(ArchivingHandlerBean.ARCHIVING_CREDHIST_AGE_IN_DAYS); result = "150"; 
      props.getProperty(ArchivingHandlerBean.ARCHIVING_DEBTHIST_AGE_IN_DAYS); result = "140"; 
      props.getProperty(ArchivingHandlerBean.ARCHIVING_LOG_AGE_IN_DAYS); result = "130"; 
     } 
    }; 

    new Expectations() { 
     { 
      Date expected = new Date(now - (160 * 24 * 60 * 60 * 1000)); 
      invoke(archivingBean, "moveCreditBasic2Archive", expected); 

      expected = new Date(now - (150 * 24 * 60 * 60 * 1000)); 
      invoke(archivingBean, "moveCreditHistory2Archive", expected); 

      expected = new Date(now - (999 * 24 * 60 * 60 * 1000)); 
      invoke(archivingBean, "moveDebtorHistory2Archive", expected); 

      expected = new Date(now - (130 * 24 * 60 * 60 * 1000)); 
      invoke(archivingBean, "moveLog2Archive", expected); 

     } 
    }; 

    Calendar cal = Calendar.getInstance(); 
    cal.setTimeInMillis(now); 
    Deencapsulation.invoke(archivingBean,"moveDataToArchive",cal, props); 
} 

請告訴我這個問題?查看第三個預計日期。這是錯誤的! (999而不是140)。 我也改變了通話的順序。我甚至公開了這些私人方法並嘗試過。所有這些變化都沒有改變結果:測試是綠色的。

這裏有什麼問題?爲什麼測試綠色?

回答

0

該測試是濫用嘲諷的API,通過嚴格和非嚴格的期望相同的模擬(archivingBean)。在這個模擬中記錄的第一個期望是非嚴格的,所以JMockit認爲它是整個測試的非嚴格模擬。

寫測試的正確方法是在測試結束時將嚴格的期望塊(帶有4次調用的那個塊)轉換爲驗證塊。 (一方面,整個測試有幾個問題:1)通常,應該通過一些公開的方法間接測試私有方法。 2)另外,私人方法不應該被嘲笑,除非有其他強有力的理由 - 在這種情況下,我可能會寫一個測試來驗證輸出文件的實際內容。 3)不要嘲笑不必要的東西,比如props - props.setProperty可以用來代替,我想。 4)使用自動裝箱 - Integer.valueOf(3) - >3)。

+0

我試圖將嚴格的期望更改爲驗證,並得到另一個錯誤。看到我的「答案」 – KFleischer

0

@Rogério: 您的假設並不完全正常。即我沒有setProperty()。我嘗試的是使用驗證塊。

可悲的是我不明白JMockit不夠好,讓它運行...

我做了兩件事情。首先,我試圖嘲笑這4種私人方法。我只想看看他們是否被叫。但我不希望有邏輯運行。 我試圖通過它延伸的第一NonStrictExpectations,阻止這樣的:

new NonStrictExpectations(archivingBean) { 
     { 
      invoke(archivingBean, "getConnection");result = connection; 
      connection.prepareStatement(anyString); result = prepStatement; 
      prepStatement.executeUpdate(); returns(Integer.valueOf(3), Integer.valueOf(0), Integer.valueOf(3)); 
      //New part 
      invoke(archivingBean, "moveCreditBasic2Archive", withAny(new Date())); 
      invoke(archivingBean, "moveCreditHistory2Archive", withAny(new Date())); 
      invoke(archivingBean, "moveDebtorHistory2Archive", withAny(new Date())); 
      invoke(archivingBean, "moveLog2Archive", withAny(new Date())); 
     } 
    }; 

在另一方面,我感動的期待,擋了下來,並使它成爲驗證塊。現在,JUnit的失敗,一個

mockit.internal.MissingInvocation: Missing invocation of: 
de.lpm.ejb.archiving.ArchivingHandlerBean#moveCreditBasic2Archive(java.util.Date pOlderThan) 
with arguments: Tue Feb 03 03:39:51 CET 2009 
on mock instance: [email protected] 
at de.lpm.ejb.archiving.ArchivingHandlerBean.moveCreditBasic2Archive(ArchivingHandlerBean.java:175) 
[...] 
Caused by: Missing invocation 

這是170-175線在ArchivingHandlerBean.java:

170: Connection connection = getConnection(); 
171: SQLService service = new SQLService(connection); 
172:    
173: PreparedStatement prepStmtMove = null; 
174:    
175: Vector<HashMap<String, String>> where_clauses = new Vector<HashMap<String,String>>(); 

我只是想確認4種私有方法與正確的日期執行。

+0

是的,我的答案並不完全正確,因爲這個測試正在做*部分*嘲弄。因此,在這種情況下,需要首先記錄期望值,以便JMockit知道*不*執行原始方法實現。驗證塊仍然可以稍後寫入,以驗證調用是否按預期發生,但這將意味着測試中的冗餘代碼。最後,由於需要調用/模擬私有方法以及使用部分模擬,嘲笑對於此測試根本不是一個好選擇。就我個人而言,我會用一種完全不同的方法。 –

+0

你能描述一下你如何測試這種情況嗎? – KFleischer

+0

我會使用兩種可能的替代方法之一:1)僅用外部輸入(「道具」等)寫出黑盒測試並輸出(寫入的檔案文件內容),不要模擬;或者2)編寫一個真正的單元測試,通過與獨立單元(從'archivingBean.moveDataToArchive'調用的私有方法提取的新單元)交互來驗證'archivingBean'行爲。 –