lanoxx
lanoxx

Reputation: 13051

Spring Boot Integration Test Inject Controller Dependencies

I am trying to write an integration test using Spring Boot that tests the transaction logic in one of my controllers.

What the test should do, is the following:

  1. Inject one of my controllers using @Inject
  2. Replace an email dependency in the controllers dependencies with a Mock, to avoid actually sending an email during the integration test.
  3. Call a method of the controller
  4. Assert that the transactions of the called method are properly rolled back when the mail sending mock throws an exception.

Now my problem is that, when the test runs, the controller is injected into my test class but all its dependencies are null. Here is my integration test:

@RunWith(SpringJUnit4ClassRunner.class)
@IntegrationTest
@SpringApplicationConfiguration(App.class)
@WebIntegrationTest
public MyIntegrationTest () {

    @Inject MyController controller;

    @Before
    public void before () {
       // replace one particular dependency of controller with a mock
    }

    @Test
    public void testFoo () { ... }
}

Due to the test being an integration test which starts up a full spring web application context, I was expecting that my controller would have all its dependencies already autowired, but that is obviously not the case and instead all dependencies are set to null.

Question: Do I need to use some additional annotations, or setup something in my @Before method? Or am I approaching the problem from a completely wrong side?

Update: Is it possible to test my Spring MVC Layer, without testing via HTTP such as with TestRestTemplate or MockMvc? But by directly

Upvotes: 2

Views: 3393

Answers (1)

Avinash
Avinash

Reputation: 4279

Test with TestRestTemplate instead of injecting the controller itself. Controllers is obviously a spring bean but if you directly inject it in your test class, it wont be able to initialize the context.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ExampleStart.class)
public class ExampleTest {
    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void exampleTest() {
        String body = this.restTemplate.getForObject("/", String.class);
        assertThat(body).isEqualTo("Hello World");
    }
}

ExampleStart.java -> The spring boot starter class

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class ExampleStart extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(ExampleStart.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(ExampleStart.class, args);
    }
}

Ref : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

But if you want to test service method, you can use @Autowired and call the methods as usual.

Upvotes: 0

Related Questions