Can't Autowire JpaRepository in Junit test - Spring boot application
Your error is actually the expected behavior of @WebMvcTest
.You basically have 2 options to perform tests on your controller.
1. @WebMvcTest - need to use @MockBean
With @WebMvcTest
, a minimal spring context is loaded, just enough to test the web controllers. This means that your Repository isn't available for injection:
@WebMvcTest
will auto-configure the Spring MVC infrastructure and limit scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver.
Assuming the goal is just to test the Controller, you should inject your repository as a mock using @MockBean
.
You could have something like:
@RunWith(SpringRunner.class)@WebMvcTest(TodoController.class)public class TodoControllerTest { @Autowired private MockMvc mvc; @Autowired private TodoController subject; @MockBean private TodoRepository todoRepository; @Test public void testCreate() throws Exception { String json = "{\"text\":\"a new todo\"}"; mvc.perform(post("/todo").content(json) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(3)) .andExpect(jsonPath("$.text").value("a new todo")) .andExpect(jsonPath("$.completed").value(false)); Mockito.verify(todoRepository, Mockito.times(1)).save(any(Todo.class)); }}
2. @SpringBootTest - you can @Autowire beans
If you want to load the whole application context, then use @SpringBootTest
: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
You'd have something like this:
@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)public class TodoControllerTest { private MockMvc mvc; @Autowired TodoController subject; @Autowired private WebApplicationContext context; @Before public void setup() { this.mvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test public void testNoErrorSanityCheck() throws Exception { String json = "{\"text\":\"a new todo\"}"; mvc.perform(post("/todo").content(json) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(3)) .andExpect(jsonPath("$.text").value("a new todo")) .andExpect(jsonPath("$.completed").value(false)); assertThat(subject.getTodos()).hasSize(4); }}