Java 模拟bean依赖项的NoSuchBeanDefinitionException

Java 模拟bean依赖项的NoSuchBeanDefinitionException,java,spring,mocking,integration-testing,mockito,cglib,Java,Spring,Mocking,Integration Testing,Mockito,Cglib,我试图在集成测试中使用mock,但运气不太好。我使用的是Spring 3.1.1和Mockito 1.9.0,情况如下: @Component public class ClassToTest { @Resource private Dependency dependency; } 及 现在,我想使用Spring的JavaConfig对ClassToTest进行集成测试。这是我尝试过的,但它不起作用: @Test @ContextConfiguration public c

我试图在集成测试中使用mock,但运气不太好。我使用的是Spring 3.1.1和Mockito 1.9.0,情况如下:

@Component
public class ClassToTest {

    @Resource
    private Dependency dependency;

}

现在,我想使用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,表示应用程序上下文中没有NestedDependence类型的bean。我不明白这一点——我以为Spring会收到Mockito的模拟依赖实例,甚至不看它的自动连接。由于这不起作用,我最终不得不模拟我的整个对象图——这完全违背了模拟的意义


提前感谢您的帮助

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

@Component
public class Dependency {

    @Resource
    private NestedDependency nestedDependency;

}


public class Dependency$EnhancerByMockito extends Dependency{
    //...
}
这意味着Spring在使用mock时仍然可以看到基类中的字段。您可以做什么:

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

  • Mock
    NestedDependency
    -我知道它只会将问题进一步级联一级

  • 禁用测试的
    @Resource
    注释扫描


  • 我也有同样的问题,我找到了另一个解决办法。 当Spring实例化所有bean时,它将检查它是否是Mockito Mock,在本例中,我返回false for injection属性。要使用它,只需在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);
        }
    
    }
    

    Mockito的cglib子类是否也继承私有字段???@TomMcIntyre:实际上它与Mockito/cglib无关。若创建
    SubDependency扩展Dependency
    普通类,Spring(通过反射)仍会找到基类中声明的私有字段。CGLIB生成的类也不例外。@Tomasz您不应该使用“继承”这个词,因为它可能会被误解。字段和方法保留在其声明类中,如果可见性修饰符允许,则可以在编译时访问这些字段和方法。在运行时,可以通过反射访问当前类或父类中的这些成员。太棒了,这让我省去了很多心痛!如果有人想知道如何注入它,请在Spring应用程序上下文XML中添加一行如下内容:
    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);
        }
    
    }