3

我有一个 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$Proxy$_$$_WeldClientProxy

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

因此,我将 MockFactory 中的 @ApplicationScoped 替换为 @Dependent ,它不会代理实例,但我有一个新问题:

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

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

谢谢。

4

3 回答 3

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);
}
}
于 2013-05-26T21:12:25.797 回答
1

下一版本的 CDI-Unit (2.1.1) 添加了对 EasyMock 的支持,其方式与当前支持 Mockito 的方式相同。

于 2013-08-12T20:56:46.073 回答
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;
    }

}
于 2013-05-29T12:44:23.203 回答