使用CDI单元和EasyMock进行单元测试

时间:2013-05-26 17:34:37

标签: unit-testing cdi easymock cdi-unit

我有一个带CDI的项目,我想用模拟创建单元测试。 为了管理模拟,我想使​​用EasyMock并运行CDI,我发现cdi-unit项目看起来很容易使用。

我在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:不是模拟:   org.jboss.weld.proxies.IStockDao $ $ -1971870620代理$ _ _ $$ WeldClientProxy

这是因为CDI没有提供EasyMock IStockDao的实例,而是一个代理实例,EasyMock不接受这些方法(如重置方法)。

所以我用@Dependent替换了MockFactory中的@ApplicationScoped,它没有代理实例,但我遇到了一个新问题:

这个注释在每个注入点给出了一个新的mock实例,所以我可以使用它,因为我在单元测试中有一个模拟测试类中调用的模拟方法。并且这个mock实例在测试类中必须是相同的(@Dependent不是这样)。

如何在单元测试和测试类中获得相同的实例?

感谢。

3 个答案:

答案 0 :(得分:3)

Needle是您测试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 :(得分:1)

我用easymock对CDI拦截器进行了单元测试,并遇到了和你一样的问题。

我想分享我用过的解决方法。 它包括在@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;
    }

}

答案 2 :(得分:1)

CDI-Unit(2.1.1)的下一个版本增加了对EasyMock的支持,就像目前支持Mockito一样。