我有一个带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不是这样)。
如何在单元测试和测试类中获得相同的实例?
感谢。
答案 0 :(得分:3)
Needle是您测试CDI的朋友。
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一样。