文章目录
- 概要
- Controller Api 测试
- 源码
- 单元测试
- 集成测试
概要
Spring Boot项目测试用例
测试方式 | 是否调用数据库 | 使用的注解 | 特点 |
---|---|---|---|
单元测试(Mock Service) | ❌ 不调用数据库 | @WebMvcTest + @MockBean | 只测试 Controller 逻辑,速度快 |
集成测试(真实数据库) | ✅ 调用数据库 | @SpringBootTest | 真实保存数据,确保数据库逻辑正确 |
Controller Api 测试
Restful Api
源码
package cn.star.framework.example.controller;
import cn.star.framework.controller.AbstractController;
import cn.star.framework.core.api.AppResult;
import cn.star.framework.core.api.Pageable;
import cn.star.framework.example.entity.Example;
import cn.star.framework.example.service.ExampleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* ExampleController<br>
*
* @author zhaoweiping
* <p style='color: red'>Created on 2025-02-06 16:16:40
* @since 3.0.0
*/
@RestController
@RequestMapping(value = "/example")
@Api(tags = "框架测试")
public class ExampleController extends AbstractController<Example, String> {
@Autowired @Getter private ExampleService service;
@Override
@PostMapping
@ApiOperation(value = "新增")
public AppResult<Example> save(@RequestBody Example entity) {
return super.save(entity);
}
@Override
@PutMapping
@ApiOperation(value = "更新")
public AppResult<Example> update(@RequestBody Example entity) {
return super.update(entity);
}
@Override
@DeleteMapping
@ApiOperation(value = "删除")
public AppResult<List<Example>> deleteByIds(@RequestBody String... ids) {
return super.deleteByIds(ids);
}
@GetMapping
@ApiOperation(value = "查询(列表)")
public AppResult<List<Example>> list(HttpServletRequest request) {
return super.list(request, Example.class);
}
@Override
@GetMapping("/{id}")
@ApiOperation(value = "查询(主键)")
public AppResult<Example> get(@PathVariable(value = "id") String id) {
return super.get(id);
}
@GetMapping("/page")
@ApiOperation(value = "查询(分页)")
public AppResult<Pageable<Example>> pageable(HttpServletRequest request) {
return super.pageable(request, Example.class);
}
}
单元测试
package cn.star.framework.example.controller;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import cn.hutool.json.JSONUtil;
import cn.star.framework.example.entity.Example;
import cn.star.framework.example.service.ExampleService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
/**
* 单元测试<br>
*
* @author zhaoweiping
* <p style='color: red'>Created on 2025-02-06 18:52:28
* @since 3.0.0
*/
@Slf4j
@RunWith(SpringRunner.class)
@WebMvcTest(ExampleController.class)
public class ExampleControllerMockTest {
@Autowired private MockMvc mockMvc;
@MockBean private ExampleService exampleService;
@Before
public void setup() {
log.info("setup ...");
}
@Test
public void save() throws Exception {
Example example = new Example("1", "新增");
// 不会调用真实数据库操作
when(exampleService.save(Mockito.any(Example.class))).thenReturn(example);
mockMvc
.perform(
post("/example")
.contentType(MediaType.APPLICATION_JSON)
.content(JSONUtil.toJsonStr(example)))
// 断言
.andExpect(status().isOk())
// 打印结果
.andDo(System.out::println)
.andDo(result -> System.out.println(result.getResponse().getContentAsString()));
}
}
集成测试
package cn.star.framework.example.controller;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
import cn.hutool.json.JSONUtil;
import cn.star.framework.core.Constant;
import cn.star.framework.example.entity.Example;
import cn.star.framework.example.service.ExampleService;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
/**
* 集成测试<br>
*
* @author zhaoweiping
* <p style='color: red'>Created on 2025-02-06 18:52:28
* @since 3.0.0
*/
@Slf4j
@RunWith(SpringRunner.class)
@EntityScan(basePackages = Constant.BASE_PACKAGE)
@EnableJpaRepositories(basePackages = Constant.BASE_PACKAGE)
@ComponentScan(basePackages = Constant.BASE_PACKAGE)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleControllerTest {
@Autowired private WebApplicationContext context;
@Autowired private ExampleService exampleService;
/** 在集成测试中不会自动创建,需要手动初始化 */
@Autowired(required = false)
private MockMvc mockMvc;
@Before
public void setup() {
log.info("setup ...");
mockMvc = webAppContextSetup(context).build();
}
@Test
public void save() throws Exception {
Example example = new Example("1", "新增");
// 不会调用真实数据库操作
System.out.println(exampleService);
mockMvc
.perform(
post("/example")
.contentType(MediaType.APPLICATION_JSON)
.content(JSONUtil.toJsonStr(example)))
// 断言
.andExpect(status().isOk())
// 打印结果
.andDo(System.out::println)
.andDo(result -> System.out.println(result.getResponse().getContentAsString()));
List<Example> examples = exampleService.findAll();
System.out.println(examples);
}
}