2013-05-26 169 views
3

我有一個CDI項目,我想用mocks創建單元測試。 要管理嘲笑,我想使用EasyMock並與CDI一起運行,我發現似乎易於使用的cdi-unit項目。單元測試與CDI單元和EasyMock

我有一個問題,在CDI上下文中使用EasyMock進行模擬。這裏是我的單元測試:

@RunWith(CdiRunner.class) 
@AdditionalClasses(MockFactory.class) 
public class ResultYearMServiceImplTest { 

    @Inject 
    private IStockDao stockDao; 

    @Inject 
    private ResultYearMServiceImpl resultYearMService; 

    @Test 
    public void getResultList() { 
     EasyMock.reset(stockDao); 
     EasyMock.expect(stockDao.getListStocks()).andReturn(null).once() 
       .andReturn(new ArrayList<DtoStock>()).once(); 
     EasyMock.replay(stockDao); 
    } 
} 

IStockDao必須模擬測試,所以要得到它,我想用一個@Produces方法是這樣的(由@AdditionalClasses給CDI單元MockFactory類):

@Produces 
@ApplicationScoped 
public IStockDao getStockDao() { 
    return EasyMock.createMock(IStockDao.class); 
} 

當我運行我的單元測試,模擬在單元測試好,但我得到這個錯誤:

java.lang.IllegalArgumentException: Not a mock: org.jboss.weld.proxies.IStockDao$-1971870620$Proxy$_$$_WeldClientProxy

這人來,因爲CDI不給EasyMock的IStockDao而是一個實例代理插件tance和EasyMock在這些方法中不接受這種方法(如重置方法)。

所以我代替@ApplicationScoped在MockFactory由@Dependent不proxified實例,但我有一個新的問題:

此註釋在每個注射點給模擬的新實例,這樣我就可以使用它,因爲我在單元測試中模擬了在被測類中調用的模擬方法。而這個模擬實例在被測試的類中必須是相同的(@Dependent並不是這種情況)。

如何在單元測試和測試類中獲得相同的實例?

謝謝。

+0

爲什麼不在測試中創建你的模擬,並使用'new ResultYearMServiceImpl(stockDao)'創建要測試的對象?這是依賴注入的要點:能夠在單元測試中手動注入模擬依賴關係。你不需要CDI來單元測試一個班級。 –

+0

我不使用CDI進行單元測試,我在整個項目中使用CDI。當應用程序運行時,ResultYearMServiceImpl自身被許多類中的CDI注入。所以我需要保持cdi進行單元測試,而不需要將我的構造函數修改爲單元測試需要 – Kiva

+0

您正在使用依賴注入。所以注入你的依賴。您可以使用構造函數,setter或reflaction技巧來訪問注入的字段。如果你的模擬框架不支持這些反射技巧,那麼使用字段注入不是明智的選擇。 Mockito使用其註釋支持現場注射。 –

回答

3

針是測試CDI的朋友。

http://needle.spree.de

public class ResultYearMServiceImplTest { 
    @Rule 
    public final NeedleRule needle = new NeedleRule(); 

    @Inject 
    private IStockDao stockDao; 

    @ObjectUnderTest 
    private ResultYearMServiceImpl resultYearMService; 
@Test 
public void getResultList() { 
    EasyMock.reset(stockDao); 
    EasyMock.expect(stockDao.getListStocks()).andReturn(null).once() 
      .andReturn(new ArrayList<DtoStock>()).once(); 
    EasyMock.replay(stockDao); 
} 
} 
1

我是單元測試CDI攔截器與EasyMock的和有同樣的問題,因爲你。

我想分享我使用的解決方法。 它包含在@Dependent範圍內生成模擬。這樣我們就可以用easymock來解決CDI代理問題。

import static org.easymock.EasyMock.createStrictControl; 

import javax.enterprise.context.ApplicationScoped; 
import javax.enterprise.context.Dependent; 
import javax.enterprise.inject.Produces; 


/** 
* Mock producer. Beans are produced in Dependent scope to not be proxied. 
*/ 
@ApplicationScoped 
public class CdiMockProducerUnitTests { 

    /** 
    * Mock 
    */ 
    private final MyMockClass myMock; 

    /** 
    * Constructor creating mocks. 
    */ 
    public CdiMockProducerTestesUnitarios() { 
     myMock = createStrictControl().createMock(MyMockClass.class); 
    } 

    /** 
    * Produces mock in dependent scope. 
    * 
    * @return mock 
    */ 
    @Produces 
    @Dependent 
    public MyMockClass produceMock() { 
     return myMock; 
    } 

} 
+0

是的,我也發現這個解決方案,但我認爲這是一個非常骯髒的解決方案。在這裏,我們只有一次模擬類,所以創建一個變量(myMock)。當你有50/60的項目在一個非常大的項目中創建時,你會怎麼做?你創建了50個變量嗎?這個解決方案很好地解決了小型項目的問題,但對於大型項目卻沒有。 – Kiva

+0

我同意並認爲最糟糕的部分是不得不編寫生產者方法。在大型項目中,您仍然需要編寫數百個製作者,每個模擬類型一個。所以,希望easymock CDI擴展很快發佈。我發現這個http://junitcdi.sandbox.seasar.org/junitcdi-easymock/index.html,但它不是很新。 – marciopd

+0

我在EasyMock的JIRA中創建了一個新的功能請求:https://jira.codehaus.org/browse/EASYMOCK-126。如果你同意,請投票。 – marciopd

1

CDI-Unit(2.1.1)的下一個版本以與Mockito當前支持相同的方式增加了對EasyMock的支持。