2011-09-16 23 views
8

例如,我有一個java類如下。我將爲doWork()編寫一個單元測試,所以我想控制obj的行爲。但很明顯obj在內部被實例化了。如何在一個方法中編寫一個UT來模擬一個內部對象?

我該如何寫這個UT?現在我正在使用Junit + Mockito。

class ToBeTest{ 
    public ToBeTest(){} 
    public boolean doWork(){ 
     OtherObject obj=new OtherObject(); 
     return obj.work(); 
    } 
} 

在此先感謝。 :)

順便說一句,現實是我寫他人的班的UT。所以我不想改變它。它已通過集成測試進行了全面測試。

+2

'obj' *是否有內部實例化?將它視爲一種依賴關係是否有意義? –

+0

你說得對。但現實是我爲他人的班級寫了UT。所以我不想改變它。它已經完全測試。 – Smartmarkey

+1

另一點。我們不能在我們的班級注入所有對象。就像我們打開一個文件一樣,所以我們需要實例化一個File類。 – Smartmarkey

回答

7

如果你不能改變代碼,你可以使用Powermock以及junit和Mockito來模擬新對象的構造。

@Test 
public void testDoWork() throws Exception{ 

    MyTest mytest = new MyTest(); 

    OtherObj obj = new OtherObj(); 
    obj.test="mocked Test"; //here you can add any other needed values to obj 

    PowerMockito.whenNew(OtherObj.class).withNoArguments().thenReturn(obj); 

    String result = mytest.doWork(); 
    Assert.assertTrue(result.equalsIgnoreCase("mocked Test")); 
} 
+0

非常感謝。這正是我需要的。我試了一下。太好了。 – Smartmarkey

1

你不容易。我可以想到兩種方法可以做到這一點,並且Mockito或jUnit都不支持Mockito或jUnit,據我所知:

1)使用cglib或類似庫的字節代碼操作,做和可能非常脆弱。

2)備用類加載器。您可以構建一個類加載器,用於查找加載OtherObject類的嘗試,並將其替換爲匿名的OtherObject類,從而爲您提供您正在查找的模擬行爲。

大多數情況下,您應該將其視爲依賴關係。如果你想測試打開一個文件,你可能真的想用一個文件測試,所以使用具體的類可能是好的。如果你想測試一個方法的行爲,將文件作爲其邏輯的一部分打開,你可以很容易地將其移出到一個依賴關係,然後將其模擬出來。事實上,這通常是有道理的,因爲有一天你在一個文件中存儲的內容可能需要存儲在另一個數據庫中,或者在第三天從雲端下載,所以將你對文件做的邏輯分開無論如何,開啓檢索內容的實際過程常常是關注的邏輯分離。

2

最好的方法是編寫代碼以支持測試Test-Driven Development正在強調這一點)。目前,您的代碼是以難以測試的方式編寫的。

考慮使用依賴注入,因爲它可以幫助你嘲笑依賴對象。

1

這是一個經典的例子,您應該使用dependency injection。簡而言之,不是在內部創建對象(依賴關係),而是在構造函數中傳遞它,或者使用工廠來創建你想要的東西(工廠在生產代碼中返回實際實現,在測試中返回實際實現)。這使您可以在測試時更改實施。

看看下面的例子,就像我提供的或谷歌的「Java依賴項注入示例」。

0

你寫了你的代碼,現在你想單元測試它。這是你困難的根本原因。我建議採用不同的方法。

  1. 快遞什麼doWork()方法意味着可以觀察到的通過ToBeTestpublicprotected(吸氣)的方法,或者public任何objectys associated-的protected方法行爲方面做與ToBeTest對象。看一下Java庫提供的Javadoc:它描述了所有這些類所做的沒有,說明了方法的主體。您的方法何時會返回true?它什麼時候返回false?它有什麼副作用?你可能會發現你需要添加一些getter方法來做到這一點。你可以express these in the Javadoc for your own code
  2. 使用所需的行爲來決定可以在單元測試中放置哪些類型的斷言。使用JMockit

    import org.junit.*; 
    import mockit.*; 
    
    @Test 
    public void justMockIt() 
    { 
        new NonStrictExpectations() { OtherObject o; { o.work(); result = true; }}; 
    
        assert new ToBeTest().doWork(); 
    } 
    

    ...:

1

這很容易。

相關問題