最近在实践测试,经常遇到一个问题,就是测试怎么写,测试粒度是怎么样的?所以狂补了一下测试相关的知识。
测试金字塔
测试金字塔将测试进行了分层,越底层的测试,实现成本越低,测试效率更高,可维护性越高,但是业务需求的反映越低
测试金字塔
如图,测试被分成了三层,从下到上分成:Unit层,UI层和Service层。
- Unit层则是我们常说的单元测试。
- Service层又可以细分,如(集成测试,功能测试,系统测试,契约测试,端到端测试)。
- UI层则是用户界面测试。
单元测试
单元测试处于金字塔最底部,这类测试的特点是:
- 只测试单独的class
- 只需要有应用的源码,而不需要跑服务实例
- 够快
- 不依赖于外部系统(web service,database)且不需要很多/基本没有I/O操作(不用建立数据库)
在Spring boot中主要有三种测试方法
- Controller测试 - 使用mockMvc
@RunWith(SpringRunner.class)
@WebMvcTest(TaskController.class)
public class TaskControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private TaskService taskService;
@Test
public void should_get_all_tasks_by_getAllTask() throws Exception {
given(taskService.getTasks())
.willReturn(Lists.newArrayList(createTask("test"), createTask("aaa")));
mockMvc.perform(MockMvcRequestBuilders.get("/tasks"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].name").value("test"))
.andExpect(jsonPath("$[1].name").value("aaa"));
}
public Task createTask(String name) {
Task task = new Task();
task.setName(name); return task;
}
}
- Service测试 - 使用Mockito
@RunWith(MockitoJUnitRunner.class)
public class TaskServiceTest {
@InjectMocks
private TaskService taskService;
@Mock
private TaskRepository taskRepository;
@Test
public void should_return_all_tasks_when_getAllTasks() {
given(taskRepository.findAll())
.willReturn(Lists.newArrayList(createTask("test"), createTask("aaa")));
List<Task> tasks = taskService.getTasks();
assertThat(tasks.size(), is(2));
assertThat(tasks.get(0).getName(), is("test"));
assertThat(tasks.get(1).getName(), is("aaa"));
}
public Task createTask(String name) {
Task task = new Task();
task.setName(name);
return task;
}
}
repository 测试 - 使用DataJpaTest
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = NONE)
public class TaskRepositoryTest {
@Autowired
private TaskRepository taskRepository;
@Autowired
private TestEntityManager entityManager;
@Test
public void get_all_will_return_all_tasks() {
List<Task> tasks = taskRepository.findAll();
assertThat(tasks.size(), is(2));
assertThat(tasks.get(0).getName(), is("test"));
assertThat(tasks.get(1).getName(), is("aaa"));
}
}
基于H2,flywayTest annotation测试的写法。
@FlywayTest可以放在3个地方
- class上面:单个class 会跑flywayclean 和flywaymigrate
- setup方法上面:每个测试都会跑flywayclean 和flywaymigrate
- 单个测试方法上面:单个测试会跑flywayclean 和flywaymigrate
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
@RunWith(SpringRunner.class)
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
FlywayTestExecutionListener.class
})
class FlywayMethodTest {
@Autowired
private UserRepository repository;
@Test
@FlywayTest
void contextLoads() {
assertThat(repository.findAll().size(), is(3));
}
}
网友评论