生活就像点菜,饥饿时菜会点得特别多,但吃一阵就会意识到浪费;如果慢条斯理地盘算怎么点菜,别人已经要吃完了。这就是决策的复杂性。
作为一个做后端开发不过一年的菜鸟来说,我对后端工程师也有一定的见解。后端工程师要有产品设计思维、代码编写能力、问题排查能力、功能自测能力(bugfree了解下,哈哈)
我个人比较看重bugfree。所以比较注重自测,一般是测试驱动开发,先写单元测试,然后设计并实现业务代码。但是多数情况下,不是在写bug就是在解决bug的路上,哈哈,还需要努力。我们公司也对开发有了严格要求,单元测试覆盖率小于60%,TOP10的团队会在大群里公示15天,可怕不。
为什么强调单元测试呢?有没有遇到过这种情况,当你写的方法被别人调用的时候,突然来个尴尬的空指针,会不会被同事追着打,哈哈。所以今天着重聊一聊单元测试。
这张图熟悉不?
其实上面的图我并不熟悉,因为我们使用Junit4,从官网上截取的。但在Java开发单元测试中最常用的Junit无疑了,接下来结合一般后端开发的MVC模式,一层一层的测试下去。
添加maven依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Spring单元测试基本结构
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
class ApplicationTests {
@Test
void contextLoads() {
}
}
开始测试Controller层
测试Controller层不就是调用接口吗?postman不香吗?哈哈,小编最常用的也是postman请求接口,但是也有了解的必要性。
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
// 开启Mock自动注入
@AutoConfigureMockMvc
class ApplicationTests {
@Autowired
MockMvc mockMvc;
@Test
public void test() throws Exception{
// 测试请求
System.out.println(mockMvc);
// perform开启一个MockMvcRequestBuilders请求,包括post和get方法
MvcResult mvcResult = mockMvc.perform(
MockMvcRequestBuilders.get("/select2")
.contentType(MediaType.APPLICATION_JSON)
// 设置请求参数
//.param("","")
// 返回状态校验
).andExpect(MockMvcResultMatchers.status().isOk())
//详细请求信息打印到控制台
.andDo(MockMvcResultHandlers.print())
// 返回打印
.andReturn();
System.out.println(mvcResult.getResponse().getContentAsString());
}
@Test
public void test2() throws Exception {
// 测试插入
ObjectMapper om = new ObjectMapper();
Book book = new Book();
book.setId(100L);
book.setName("三国");
String s = om.writeValueAsString(book);
MvcResult mvcResult = mockMvc.perform(
MockMvcRequestBuilders.post("/select2")
.contentType(MediaType.APPLICATION_JSON)
.content(s)
).andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
System.out.println(mvcResult.getResponse().getContentAsString());
}
}
Service层
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
class ApplicationTests {
// 进行注入
@Autowired
private UserService userService;
// 匹配
@Test
void contextLoads() {
List<Book> books = userService.testUserMapper2();
Assert.assertThat(books.size(), Matchers.is(1));
}
}
测试json(重点了解一下)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AspectLockApplication.class)
//添加json序列化和反序列化测试
@JsonTest
public class Test {
@Autowired
JacksonTester<Book> jacksonTester;
@org.junit.Test
public void test() throws Exception{
Book book = new Book();
book.setAge(10);
book.setHabies(Arrays.asList("码代码"));
book.setName("wencaixu");
book.setTime(new Date());
// 定义在当前包下的json文件
Assertions.assertThat(jacksonTester.write(book)).isEqualToJson("book.json");
// 判断序列化结果是否所续期的json
Assertions.assertThat(jacksonTester.write(book)).hasJsonPathStringValue("@.name");
// 判断值
Assertions.assertThat(jacksonTester.write(book)).extractingJsonPathStringValue("@.name").isEqualTo("码代码");
}
@org.junit.Test
public void testDeserialize() throws Exception{
String content = "{\"id\":1}";
Assertions.assertThat(jacksonTester.parseObject(content).getName()).isEqualTo("码代码");
}
}
看完上面的文章,代码很简单,还是需要多看api文档和官方文档,我想大概大家应该都知道如何对代码进行单元测试了吧,更多的文章在看相声也要敲代码(个人公众号)。