NoSuchBeanDefinitionException for mocked beans dependencies

I am trying to use mocks in my integration test and am not having much luck. I am using Spring 3.1.1 and Mockito 1.9.0 and the situation is like this:

@Component
public class ClassToTest {

    @Resource
    private Dependency dependency;

}

      

and

@Component
public class Dependency {

    @Resource
    private NestedDependency nestedDependency;

}

      

Now I want to perform an integration test ClassToTest using Spring JavaConfig. This is what I tried and it doesn't work:

@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);
        }

    }
}

      

I have simplified the setup to make the question easier to understand. Actually I have more dependencies and I only want to mock some of them - others are real, based on the configuration imported from my prod @Configuration classes.

As a result, I get a NoSuchBeanDefinitionException saying there are no beans of type NestedDependency in the application context. I don't get it - I thought Spring would get Mockito, a mocking Dependency instance, and wouldn't even look at its autodevice. Since that doesn't work, I have to mock my whole object graph which completely hits the point of mockery!

Thanks in advance for your help!

+3


source to share


2 answers


What Mockito does when mocking classes is it creates a subclass using with some fancy name: Dependency$EnhancerByMockito

(IIRC). As you probably know, subclasses inherit fields from their parent:

@Component
public class Dependency {

    @Resource
    private NestedDependency nestedDependency;

}


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

      



This means that Spring can still see the field in the base class when the layout is presented. What can you do:

  • Use interfaces that will force Mockito to use dynamic proxies rather than CGLIB classes

  • Mock NestedDependency

    - I know it just cascades the problem one level further

  • Disable @Resource

    annotation scanning for tests

+2


source


I had the same problem and found a different solution. When Spring instantiates all of your beans, it checks if it is a Mockito Mock, in which case I return false for the injection property. To use it, just put it in your Spring context

Code below:



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);
    }

}

      

+4


source







All Articles