Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test in Spring: injecting a dependency into a component under test

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?

like image 572
Damian Nadales Avatar asked Dec 11 '15 19:12

Damian Nadales


People also ask

How does dependency injection work in unit testing?

Dependency injection allows unit testing, but it also allow modification of an object's behavior without altering the code of that object (open/closed principle). So, it isn't just testable code, but flexible code that results.

Is dependency injection required for unit testing?

Unit testing is challenging when you add frameworks around your tests subjects. Dependency injection is one of those patterns supported by frameworks, that we usually need in any project.

What is dependency injections in spring?

Dependency Injection is a fundamental aspect of the Spring framework, through which the Spring container “injects” objects into other objects or “dependencies”. Simply put, this allows for loose coupling of components and moves the responsibility of managing components onto the container.

How do you inject a bean in a spring test?

Due to this, we can inject any bean from the application context by autowiring the bean into our test class: @SpringBootTest @TestPropertySource(locations="classpath:test. properties") class TestConfigurationExampleAppTests { @Autowired private DataService dataService; ... }


1 Answers

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.

like image 62
JB Nizet Avatar answered Oct 06 '22 07:10

JB Nizet