I have a very simple rest controller:
@RestController
public class MyController {
@Autowired
public Logger logger;
The logger dependency gets injected via the following configuration:
@Configuration
public class MyConfig {
@Bean
public Logger logger() {
return LoggerFactory.getLogger(MyController.class);
}
If I run the Spring application that contains the controller then everything works fine. However, I cannot manage to achieve this dependency injection when running my unit tests. In this case I have the following test configuration:
@Configuration
@Profile("test")
public class MyTestConfig {
@Bean
public Logger logger() {
return LoggerFactory.getLogger(MyCOntroller.class);
}
And this is the relevant part of my unit tests code:
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(classes = MyTestConfig.class)
@ActiveProfiles("test")
public class MyContollerTest {
However the logger object does not get "autowired" in MyController
(note that I do not want to mock the logger object), which results in a null pointer reference.
What am I missing?
A unit test shouldn't use any Spring configuration. You should simply instantiate your component, and inject dependencies (usually fake ones) manually.
You used field injection, which makes it a bit harder. With constructor injection, all you would need to do is
Logger logger = LoggerFactory.getLogger(MyController.class);
MyController controller = new MyController(logger);
Mockito can help injecting fake dependencies for you, though, even when using field injection, thanks to the @Mock
, @Spy
and @InjectMocks
annotations:
@Spy
private Logger logger = LoggerFactory.getLogger(MyController.class);
@InjectMocks
private MyController controller;
@Before
public void prepare() {
MockitoAnnotations.initMocks(this);
}
That said, if I'm not mistaken, you're not using @RunWith(SpringJUnit4ClassRunner.class)
, so your test runner doesn't know anything about Spring, and thus doesn't create or use any Spring configuration.