hublo hublo - 4 months ago 64
Java Question

Springboot Unit Test Autowired

I have the following classes :

ApplicationAndConfiguration class

package mypackage.service;

import mypackage.service.util.MyUtility;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ApplicationAndConfiguration {


public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ApplicationAndConfiguration.class, new String[]{});
}

@Bean(initMethod="init")
public MyUtility birtUtil() {
return new MyUtility();
}
}


MyRestController class

package mypackage.service.controllers;

import mypackage.service.util.MyUtility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyRestController {

@Autowired
private MyUtility util;

@RequestMapping("/getLibraryName")
public String getMessageFromRest(@RequestParam String name) {

return "name was " + name + "//" + util.getMessage();
}
}


MyUtility class

package mypackage.service.util;

public class MyUtility {

private String message;

public void init() {
setMessage("MyUtility correctly initialized!");
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}


When I start the application and run it as an independant jar, or from the IDE (Eclipse), no problem at all, everything works as expected.

However, I want to write a unit test to test my MyRestController class ... and I'm getting a NPE because the Autowired field util is null (within MyRestController class).

Here is my test class :

package mypackage.service.controllers;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import mypackage.service.ApplicationAndConfiguration;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@SpringApplicationConfiguration(classes = ApplicationAndConfiguration.class)
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class TestController {

private MockMvc mvc;

@Before
public void setup() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new MyRestController()).build();
}

@Test
public void MyTestController() throws Exception {

mvc.perform(MockMvcRequestBuilders.get("/getLibraryName").param("name", "test").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("name was test//MyUtility correctly initialized!")));
}
}


I'm definitely missing something so that my Autowired field gets filled during tests, and not only during standard application execution ...

Any pointer why it doesn't work ?

Answer

MockMvc standalone setup is for unit testing. You are doing integration testing when you are creating Spring context in test. Don't mix these two types of testing.

So just change it this way:

@SpringApplicationConfiguration(classes = ApplicationAndConfiguration.class)
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class TestController {

    private MockMvc mvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setup() throws Exception {
        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }