Reputation: 1171
Is it possible to somehow have in the same test class @MockBean
and @Autowired
of the same service?
In other words, I would like to have @MockBean
service only for one test, while for others tests of the same class I need it as @Autowired
.
Upvotes: 14
Views: 13950
Reputation: 2280
The best solution is to change @MockBean
to @SpyBean. And in the method you will be able to do like this:
kotlin
@SpyBean
lateinit var serviceMock: Service
@Test
fun smallTest()
`when`(serviceMock.doSomething())
.thenReturn(false)
// your test logic
}
Upvotes: 10
Reputation: 1564
This relies on the difference between @MockBean
and @Autowired
.
@Autowired
only does a lookup in the SpringContext
for a bean of that type. This means that you will need to create that bean if you need to 'autowire' it
@MockBean
does exactly what you expect from the name, it creates a 'mock' of the service, and injects it as a bean.
so this
class MyTest {
@MockBean
MyService myService;
}
is equivalent to this
@Import(MyTest.Config.class)
class MyTest {
@Autowired
MyService myService;
@TestConfiguration
static class Config {
@Bean
MyService myService() {
return Mockito.mock(MyService.class);
}
}
}
So, if you need to have a different bean of the MyService
type in other tests, you need to create the bean in a @TestConfiguration
annotated class
@Import(MyTest.Config.class)
class MyTest {
@Autowired
MyService myService;
@TestConfiguration
static class Config {
@Bean
MyService myService() {
return new MyServiceImpl();
}
}
}
Or, in a class annotated with @Configuration
@Import(MyConfig.class)
class MyTest {
@Autowired
MyService myService;
}
@Configuration
public class MyConfig {
@Bean
MyService myService() {
return new MyServiceImpl();
}
}
Upvotes: 6
Reputation: 6581
I suspect that the source of the evil here is field injection.
Olvier Gierke (now Drotbohm) wrote a blog post about why field injection is evil.
If you can switch to constructor injection you can mock the service just in your test and pass the mock to the class you want to test.
I just want to leave this answer here as a suggestion for others who might have the chance to use constructor injection instead.
Upvotes: 1