【发布时间】:2013-05-21 15:28:43
【问题描述】:
我有一个 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,它不会代理实例,但我有一个新问题:
这个注解在每个注入点提供了一个新的模拟实例,所以我可以使用它,因为我在单元测试中有一个模拟来模拟在测试类中调用的方法。而且这个mock实例在被测类中必须是一样的(@Dependent不是这样)。
如何在单元测试和被测类中获取相同的实例?
谢谢。
【问题讨论】:
-
你为什么不在测试中创建你的模拟,并使用
new ResultYearMServiceImpl(stockDao)创建要测试的对象?这就是依赖注入的重点:能够在单元测试中手动注入模拟依赖。您不需要 CDI 来对类进行单元测试。 -
我不使用 CDI 进行单元测试,我使用 CDI 进行整个项目。当应用程序运行时,ResultYearMServiceImpl 本身是由 CDI 在许多类中注入的。所以我需要保留 cdi 进行单元测试,而不需要修改我的构造函数来满足单元测试的需要
-
您正在使用依赖注入。所以注入你的依赖。您可以使用构造函数、设置器或反射技巧来访问注入的字段。如果您的模拟框架不支持这些反射技巧,那么使用字段注入就不是明智的选择。 Mockito 使用其注释支持字段注入。
-
EasyMock 可以很好地与 Spring 配合使用(我在另一个项目中使用它),因此为了避免针对每个项目进行更改,我更喜欢使用相同的框架。我知道 Mockito 可以做到,但我的问题是:EasyMock 有可能吗?
标签: unit-testing cdi easymock cdi-unit