BYTECODES

Spring Boot controller怎么做单元测试

Spring boot单元测试首先要引入测试类库,比如在build.gradle中加入

testImplementation 'org.springframework.boot:spring-boot-starter-test'

写单元测试时,可以把controller当成普通类来测试,这个时候service层是Mock出来的

public class UserControllerUnitTest {
    private UserController controller;

    @Mock
    private IUserService userService;

    @BeforeEach
    private void initCases(){
        controller = new UserController(userService);
    }

    @Test
    public void testSave() {
        User user = new User();
        user.setUsername("root");
        user.setPassword("abcd1234");
        Result result = controller.add(user);
        Assertions.assertTrue(result.isSuccess());
    }
}

或者使用@WebMvcTest,比如这样

@WebMvcTest(UserController.class)
@Import(OtherComponent.class)
public class WebMockTest {

    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private IUserService userService;
    
    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void testSave() throws Exception {
        User user = new User();
        user.setUsername("root");
        user.setPassword("abcd1234");
        user.setName("test");

        this.mockMvc.perform(
                        post("/api/user")
                                .content(objectMapper.writeValueAsString(user))
                                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
                )
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.success", is(true)));
    }
}

@WebMvcTest只会加载@Controller和@ControllerAdvice的组件,如果需要spring加载其他组件,可以使用@Import导入


还有一种写controller层测试是这样的, 这个也不会启动web服务器,但下层的service和dao都会加载到spring环境中

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;
    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void testSave() throws Exception {
        User user = new User();
        user.setUsername("root");
        user.setPassword("abcd1234");
        user.setName("test");

        this.mockMvc.perform(
                        post("/api/user")
                                .content(objectMapper.writeValueAsString(user))
                                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
                )
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.success", is(true)));
    }
}

最后如果使用@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT),会启动web服务器,影响测试速度,但这个也是最接近真实环境的