2009-12-30 557 views
10

我們正在爲使用Spring自動裝配注入作爲接口實例的依賴項的類編寫JUnit測試。由於被測試的類永遠不會明確地實例化依賴關係或者將它傳遞給了構造函數,所以JMockit似乎也沒有義務實例化它。使用JMockit模擬自動裝配的接口實現

到目前爲止,我們一直在使用SpringRunner來爲我們提供Spring加載模擬依賴項,我們不喜歡這件事的兩件事是1)每次運行測試都不是很快,Spring框架必須被加載和初始化; 2)我們被迫顯式地創建所有的模擬依賴作爲真正的類, JMockit有助於消除。

下面是我們正在測試什麼的一個簡單的例子:

public class UnitUnderTest { 

    @Autowired 
    ISomeInterface someInterface; 

    public void callInterfaceMethod() { 

     System.out.println("UnitUnderTest.callInterfaceMethod calling someInterface.doSomething"); 
     someInterface.doSomething(); 
    } 

} 

所以,問題是,是否有辦法有JMockit創建一個模擬someInterface

+0

另請參閱:http://stackoverflow.com/questions/1638911/mock-object-and-spring-annotations – 2009-12-30 16:04:54

回答

10

JMockit將總是實例化一個嘲笑接口(除了在最後的模擬場的情況下),但是這僅發生在測試代碼。它不會自動將實例注入到測試中的代碼中。

您將不得不手動注入模擬實例。例如:

public class SomeTest 
{ 
    @Autowired UnitUnderTest unitUnderTest; 
    @Mocked ISomeInterface theMock; // created and assigned automatically 

    @Test 
    public void testSomeMethod() 
    { 
     Deencapsulation.setField(unitUnderTest, theMock); 
     //proceed with unit test here 
    } 
} 

mockit.Deencapsulation是基於反射的實用工具類,可以讓你調用私有方法,獲取/設置字段等

+4

請注意:自從發佈此答案後,JMockit添加了對自動將模擬對象注入到測試類中的支持。在本例中,用'@ Tested'和'@ Mocked'替換'@ Autowired'和'@ Injectable'。 – 2012-10-11 17:31:46

+0

哇@Rogério!這很好! JMockit非常強大...我很喜歡它! – 2014-07-04 18:39:36

+0

@Rogério可以使用jmockit覆蓋工具爲mockito生成報告嗎?我們的傳統測試代碼是mockito。任何鏈接都很有幫助。 – yuyue007 2015-01-19 11:00:26

8

您可以使用org.springframework.test.util.ReflectionTestUtils明確地將您的模擬ISomeInterface注入您的測試用例。

參見documentation

+1

(+1)這是一個很好的類,我不知道:) – Bozho 2009-12-30 15:20:05

+0

我愛找到這些Spring API中的小寶石... +1 – skaffman 2009-12-30 15:33:18

+0

這是一個很有用的類。儘管如此,不得不明確地創建模擬失敗首先使用JMockit的主要原因之一。 – SwimsZoots 2009-12-30 18:23:24

4

通過上面熱心提供的線索,這裏是我發現的最有用的對JMockit來說很新的人:JMockit提供了Deencapsulation類,允許您設置私有從屬字段的值(不需要拖動Spring庫)以及MockUp類,該類允許您顯式創建接口和模擬的實現界面的一種或多種方法。以下是我如何解決這個特殊情況的結果:

@Before 
public void setUp() { 

    IMarketMakerDal theMock = new MockUp <IMarketMakerDal>() { 

     @Mock 
     MarketMakerDcl findByMarketMakerGuid(String marketMakerGuid) { 

     MarketMakerDcl marketMakerDcl = new MarketMakerDcl(); 
     marketMakerDcl.setBaseCurrencyCode(CURRENCY_CODE_US_DOLLAR); 
     return marketMakerDcl; 
     } 
    }.getMockInstance(); 

    setField(unitUnderTest, theMock); 
} 

感謝大家的幫助。

2

對於使用jmockit時嘲笑在spring(或)框架@autowired場誰見了

java.lang.IllegalStateException: Missing @Injectable for field *** 

java.lang.IllegalStateException: Missing @Tested class for field *** 

錯誤的人,我做了以下兩個步驟,以避免上述錯誤:

  1. 使用的代替@Tested

https://groups.google.com/forum/#!msg/jmockit-users/uo0S51lSX24/lQhLNN--eJcJ

  • 復歸jmockit的版本回1.18或以前的
  • https://groups.google.com/forum/#!topic/jmockit-users/wMFZggsA8LM

    0

    如果您有一個接口的@Qualifier批註,您需要將它的@Injectable字段完全按照它在限定符中的名稱命名。

    這裏是JMockit doc報價:

    自定義名稱從Java EE的(@資源(名稱),@Named)或Spring框架(@Qualifier)字段說明指定尋找匹配時使用@Injectable或@Tested值。當這樣的名字包含 - (短劃線)或。 (點)字符,則使用相應的駱駝式名稱。

    例如:

    @Component 
    public class AClass { 
    
        @Autowired 
        private Bean1 bean1; 
    
        @Autowired 
        @Qualifier("my-dashed-name") 
        private AmqpTemplate rpcTemplate; 
    } 
    

    的單元測試類:

    public class AClassTest { 
    
        @Injectable 
        private Bean1 bean1; 
    
        @Injectable 
        private AmqpTemplate myDashedName; 
    
        @Tested 
        private AClass aClass = new AClass(); 
    } 
    

    也沒有必要使用setFiled每個@Autowired豆,各個領域注入時自動@Tested類實例化。在JMockit版本上測試1.30