【问题标题】:unit test with CDI Unit and EasyMock使用 CDI Unit 和 EasyMock 进行单元测试
【发布时间】: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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我正在使用 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;
        }
    
    }
    

    【讨论】:

    • 是的,我也找到了这个解决方案,但我认为这是一个非常肮脏的解决方案。这里我们只有一次模拟类,所以要创建一个变量(myMock)。当您在一个非常大的项目中创建 50/60 时,您会怎么做?你创建 50 个变量吗?此解决方案可以很好地解决小型项目的问题,但不适用于大型项目。
    • 我同意并认为最糟糕的部分是必须编写生产者方法。在大型项目中,您仍然需要编写数百个生产者,每个模拟类型一个。所以,希望easymock CDI 扩展能尽快发布。我找到了这个junitcdi.sandbox.seasar.org/junitcdi-easymock/index.html,但它不是很更新。
    • 我在 EasyMock 的 JIRA 中创建了一个新功能请求:jira.codehaus.org/browse/EASYMOCK-126。如果您同意,请投票。
    【解决方案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-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      相关资源
      最近更新 更多