4

I would like to test my CRUD REST Controller for the first time. I have watched some videos and come up with this idea but I am getting error. I am using JPA with mySql. ITodoService is simple interface with CRUD methods. My rest Controller is working when I test it via Postman, so code there is ok. If you could give me some feedback what might be wrong and where can I check for good imformation about testing REST app because I have spent like 3 hrs without any success :)

    @SpringBootTest
    @RunWith(SpringRunner.class)
    @WebMvcTest
    public class TodoFinalApplicationTests {

        @Autowired
        private MockMvc mockMvc;


        @MockBean
        private ITodosService iTodosService;


        @Test
        public void getAllTodosTest() throws Exception {

            Mockito.when(iTodosService.findAll()).thenReturn(
                        Collections.emptyList()
                        );

                        MvcResult mvcResult = mockMvc.perform(
                        MockMvcRequestBuilders.get("/todos")
                        .accept(MediaType.APPLICATION_JSON)
                        ).andReturn();

                        System.out.println(mvcResult.getResponse());

                        Mockito.verify(iTodosService.findAll());

        }
    }


    Error message:
    java.lang.IllegalStateException: Configuration error: found multiple declarations of @BootstrapWith for test class [com.damian.todo_Final.TodoFinalApplicationTests]: [@org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.context.SpringBootTestContextBootstrapper), @org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper)]

EDIT:
This is code for whole CRUD REST Test 
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(classes = TodoFinalApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
// @WebMvcTest
public class TodoFinalApplicationTests {

    @Autowired
    private TestRestTemplate restTemplate;



    @LocalServerPort
    private int port;

    private String getRootUrl() {
            return "http://localhost:" + port;
    }

    @Test
    public void contextLoads() {

    }



    @Test
    public void getAllTodos() {

        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> entity = new HttpEntity<String>(null, headers);
        ResponseEntity<String> response = restTemplate.exchange(getRootUrl() + "/employees",
                HttpMethod.GET, entity, String.class);
        assertNotNull(response.getBody());

    }

    @Test
    public void createNewTodo() {

        Todos todo = new Todos();
        todo.setId(5);
        todo.setTaskDate("15.01.1990");
        todo.setTaskStatus(true);
        todo.setTaskDescritpion("Description for testing");

        ResponseEntity<Todos> postResponse = restTemplate.postForEntity(getRootUrl() + "/todos", todo, Todos.class);
        assertNotNull(postResponse);
        assertNotNull(postResponse.getBody());

    }

    @Test
    public void testUpdateTodo() {
        int id = 1;
        Todos todo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
        todo.setTaskDate("15.01.1990");
        todo.setTaskStatus(true);
        todo.setTaskDescritpion("Updating");
        restTemplate.put(getRootUrl() + "/todos/" + id, todo);
        Todos updatedTodo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
        assertNotNull(updatedTodo);


    }


    @Test
    public void testDeletedTodo() {
        int id = 3;
        Todos todo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
        assertNotNull(todo);
        restTemplate.delete(getRootUrl() + "/todos/" + id);
        try {
            todo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
        } catch (final HttpClientErrorException e) {
            assertEquals(e.getStatusCode(), HttpStatus.NOT_FOUND);
        }
    }
kaktusx22
  • 59
  • 1
  • 1
  • 8

1 Answers1

7

You have both @SpringBootTest and @WebMvcTest on one test class. Both classes, among others, specify only what beans should be instantiated in the test context. The definitions are conflicting, so only one is allowed.

Decide if you want to test:

  • entire application context - use @SpringBootTest
  • only controllers - use @WebMvcTest

In your case, I would:

  • remove @SpringBootTest
  • specify Controller you want to test in @WebMvcTest

Alternatively, you can

  • remove @WebMvTest
  • add AutoConfigureWebMvc

@SpringBootTest brings all beans into context, and thus @WebMvcTest will likely result in a faster test.

Lesiak
  • 22,088
  • 2
  • 41
  • 65
  • Ahh, that is a case :). Ok thank you. When I run this test I am getting java.lang.NullPointerException at com.damian.todo_Final.TodoFinalApplicationTests.getAllTodosTest(TodoFinalApplicationTests.java:49). My code for testing has some bug, or my RestController is causing this problem? Cheers – kaktusx22 May 30 '19 at 14:05
  • Please check which variable is null, it is impossible to find out without actual line numbers. – Lesiak May 30 '19 at 14:40
  • FYI: The `@RestClientTest` annotation will also conflict with `@SpringBootTest` because it includes the `@BootstrapWith` annotation. When I upgraded the Spring Boot dependency version, I had to remove `@SpringBootTest` and add `@ConfigurationContext` to specify the test configuration class to correct the issue. – Jack Straw Apr 30 '20 at 18:56
  • @JackStraw I think you meant `@ContextConfiguration` – ssasi Sep 27 '22 at 12:43