对于模拟bean的依赖关系的NoSuchBeanDefinitionException

时间:2012-04-10 16:37:47

标签: java spring mocking integration-testing mockito

我试图在我的集成测试中使用模拟并且没有太多运气。我使用的是Spring 3.1.1和Mockito 1.9.0,情况如下:

@Component
public class ClassToTest {

    @Resource
    private Dependency dependency;

}

@Component
public class Dependency {

    @Resource
    private NestedDependency nestedDependency;

}

现在,我想使用Spring的JavaConfig对ClassToTest进行集成测试。这就是我所尝试的,它不起作用:

@Test
@ContextConfiguration
public class ClassToTestIntegrationTest {

    @Resource
    private ClassToTest classToTest;

    @Resource
    private Dependency mockDependency;

    @Test
    public void someTest() {
        verify(mockDependency).doStuff();

        // other Mockito magic...

    }


    @Configuration
    static class Config {

        @Bean
        public ClassToTest classToTest() {
            return new ClassToTest();
        }

        @Bean
        public Dependency dependency() {
            return Mockito.mock(Dependency.class);
        }

    }
}

我简化了设置,使问题更容易理解。实际上我有更多的依赖关系,只想模拟其中一些 - 其他是真实的,基于从我的prod @Configuration类导入的配置。

最终发生的事情是我得到一个NoSuchBeanDefinitionException,说明在应用程序上下文中没有类型为NestedDependency的bean。我不明白这一点 - 我认为Spring会收到Mockito嘲笑的Dependency实例,甚至不会看自动装配它。由于这不起作用,我最终不得不模拟我的整个对象图 - 这完全打败了嘲弄点!

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

我有同样的问题,我找到了另一个解决方案。 当Spring实例化你的所有bean时,它将检查它是否是Mockito Mock,在这种情况下,我返回false作为注入属性。要使用它,只需将它注入Spring上下文

以下代码:

public class MockBeanFactory extends InstantiationAwareBeanPostProcessorAdapter {

    private static final MockUtil mockUtil = new MockUtil();

    public MockBeanFactory() {
        super();
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return !mockUtil.isMock(bean);
    }

}

答案 1 :(得分:2)

Mockito在模拟类时所做的是它使用创建一个子类,其中有一些奇特的名称,如:Dependency$EnhancerByMockito(IIRC)。您可能知道,子类从其父级继承字段:

@Component
public class Dependency {

    @Resource
    private NestedDependency nestedDependency;

}


public class Dependency$EnhancerByMockito extends Dependency{
    //...
}

这意味着当使用mock时,Spring仍会在基类中看到该字段。你能做什么:

  1. 使用接口,这将导致Mockito使用动态代理而不是CGLIB生成的类

  2. 模拟NestedDependency - 我知道它会将问题进一步级联

  3. 禁用@Resource测试的注释扫描