I am using Spring, Junit and Mockito. I need to override beans defined in the main spring configuration using another mockito test configuration (injecting mock beans only as needed). Nested beans have been @Autowired
in the application.
Update:
Based on alfcope's answer below, it is important to add the name
attribute so that spring can allow the primary bean (mock) to override the original one. Otherwise you get this exception:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
The info message in the spring log shows:
Skipping bean definition for [BeanMethod:name=bar,declaringClass=test.package.MockitoTestConfiguration]: a definition for bean 'bar' already exists. This top-level bean definition is considered as an override.
Example:
I have a simplified example below that works. Here, Bar is the nested inside Foo, and I need to mock Bar for testing:
@Component
public class Foo
{
@Autowired
private Bar bar;
public String getResponseFromBar(String request)
{
String response = bar.someMethod(String request);
//do something else with this reponse
return response;
}
}
@Component
public class Bar {
public String someMethod(String request) {
String response = null;
//do something
return response;
}
}
Now for testing, let's say I want to inject a mockbar instead of the real bar. How can I achieve this in my test class below?
@Profile("test")
@Configuration
public class MockitoTestConfiguration {
//adding the name attribute is important.
@Bean(name="mockBar")
@Primary
public Bar bar() {
logger.debug("injecting mock bar");
return Mockito.mock(Bar.class);
}
}
Actual test case:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:test-context.xml")
public class FooTest {
@Autowired
Foo foo;
@Autowired
Bar mockBar; //need this to set up the mock response in the test case.
@Test
public void testAMethodInFoo_WithBarInjectedByMockito() {
//set up the mockBar response
Mockito.when(mockBar.someMethod("1")).thenReturn("1-response");
String response = foo.getResponseFromBar();
assertEquals("1-response", response);
}
}