Spring Boot REST控制器测试报错:@BootstrapWith重复声明排查
Hey there, let's break down your problem and sort this out step by step!
问题根源分析
The error you hit is caused by conflicting test annotations:
@SpringBootTestand@WebMvcTestboth carry the@BootstrapWithannotation under the hood, which tells Spring how to initialize the test context.- When you use both on the same test class, Spring gets confused— it doesn't know which context bootstrapper to use, hence the
IllegalStateExceptionabout multiple@BootstrapWithdeclarations.
To clarify the difference between the two annotations:
@WebMvcTestis a lightweight annotation for testing only the Spring MVC layer (controllers, converters, filters). It loads a minimal context and expects you to mock dependencies like yourITodosService.@SpringBootTestloads the full Spring application context, suitable for end-to-end integration tests where you want to test the complete flow (controller → service → database).
Fixes & Optimizations for Your Tests
Option 1: Pure MVC Layer Test (Use @WebMvcTest)
If you only want to validate your controller logic (without spinning up the full app), stick with @WebMvcTest and remove @SpringBootTest. Also, fix the small syntax error in your Mockito.verify call:
@RunWith(SpringRunner.class) @WebMvcTest(TodoController.class) // Specify the exact controller to test (narrow context) public class TodoControllerMvcTest { @Autowired private MockMvc mockMvc; @MockBean private ITodosService iTodosService; @Test public void getAllTodosTest() throws Exception { // Stub the service call Mockito.when(iTodosService.findAll()).thenReturn(Collections.emptyList()); // Perform request and assert responses mockMvc.perform(MockMvcRequestBuilders.get("/todos") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().json("[]")); // Use assertions instead of print // Verify the service method was called Mockito.verify(iTodosService).findAll(); // Correct syntax: verify object, then method } }
Option 2: Full Integration Test (Use @SpringBootTest)
Your modified code uses this approach, which is great for end-to-end validation. Here are a few tweaks to make it more robust:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) // Use random port to avoid conflicts @AutoConfigureMockMvc public class TodoIntegrationTest { @Autowired private MockMvc mockMvc; @Autowired private ITodosService todosService; @Autowired private TodoRepository todoRepository; // Reset database before each test to ensure isolation @BeforeEach void setUp() { todoRepository.deleteAll(); } @Test public void getAllTodos_returnsEmptyList_whenNoTodosExist() throws Exception { mockMvc.perform(get("/todos").accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().json("[]")); } @Test public void createTodo_returnsCreatedTodo() throws Exception { String todoJson = """ { "taskDate": "15.01.1990", "taskStatus": true, "taskDescritpion": "Test description" } """; mockMvc.perform(post("/todos") .contentType(MediaType.APPLICATION_JSON) .content(todoJson)) .andExpect(status().isCreated()) .andExpect(jsonPath("$.taskDescritpion").value("Test description")) .andExpect(jsonPath("$.id").isNotEmpty()); } // Add your update/delete tests with similar assertion patterns }
Note: In your original modified code, the getAllTodos method calls /employees instead of /todos— that's a copy-paste error you'll want to fix!
Recommended Learning Resources for REST App Testing
- Spring Boot Official Testing Guide: The most authoritative source, covering all test annotations (
@WebMvcTest,@SpringBootTest,@DataJpaTest) and their use cases. - Spring in Action (6th Edition): Has a dedicated chapter on testing Spring applications, with clear examples from unit tests to full integration tests.
- Mockito Official Documentation: Essential for mastering mocking/stubbing of service layers when testing controllers.
- Testing Spring Boot Applications (Official Spring Tutorial): A deep dive into tools like MockMvc, TestRestTemplate, and Testcontainers for database integration tests.
内容的提问来源于stack exchange,提问作者kaktusx22

