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 ?
To check the Service class, we need to have an instance of the Service class created and available as a @Bean so that we can @Autowire it in our test class. We can achieve this configuration using the @TestConfiguration annotation.
The @Profile(“test”) annotation is used to configure the class when the Test cases are running. Now, you can write a Unit Test case for Order Service under the src/test/resources package. The complete code for build configuration file is given below.
if you are writing unit tests a recommend you use @Mock and @InjectMocks . But if you really want test all the flow and need to inject classes, you can @RunWith(SpringJUnit4ClassRunner. class) and @Autowired your classes. Hello pedroso.
Unit Tests should be written under the src/test/java directory and classpath resources for writing a test should be placed under the src/test/resources directory. For Writing a Unit Test, we need to add the Spring Boot Starter Test dependency in your build configuration file as shown below.
Since SpringBoot 1.4, all the classes changed and deprecated https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.4.0-M2-Release-Notes. Replace the Runner and Configuration with the ones below. SpringRunner will detect the test framework for you.
@RunWith(SpringRunner.class) @SpringBootTest(classes = { FileService.class, AppProperties.class, DownloadConfigEventHandler.class }) @EnableConfigurationProperties public class ConfigMatrixDownloadAndProcessingIntegrationTests extends ConfigMatrixDownloadAbstractTest { // @Service FileService @Autowired private FileService fileService; // @Configuration AppProperties @Autowired private AppProperties properties; // @Compoenet DownloadConfigEventHandler @Autowired private DownloadConfigEventHandler downloadConfigEventHandler; .. .. }
All of these instances will be autowired as expected! Even Spring Events with the Publisher is working as expected as in https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With