文章目录
Spring boot test
上一节 Spring boot servlet,filter,Listener,Interceptor
Spring boot servlet,filter,Listener,Interceptor
源码
Test 框架简单说明使用
这里只是简单介绍了java中的测试框架的断言使用,更多应用或者深入使用,请自行查阅。
测试类规范: 测试类 以Test 结尾, 测试方法以test 开头,并且是public void 的
测试注解
- @Test
标注为一个测试方法 - @Before
标注到普通方法,每个test方法执行前执行 - @After
标注到普通方法,每个test方法执行后执行 - @BeforeClass
标注到 static 方法上,在该test类中的test方法执行之前执行,多个test方法执行只执行一次 - @AfterClass
标注到 static 方法上,在该test类中的test方法执行之后执行,多个test方法执行只执行一次
示例
// 标注到普通方法,每个test方法执行前执行
@Before
public void testBefore() {
System.out.println("testBefore");
}
// 标注到普通方法,每个test方法执行后执行
@After
public void testAfter() {
System.out.println("testAfter");
}
// 标注到 static 方法上,在该test类中的test方法执行之前执行,多个test方法执行只执行一次
@BeforeClass
public static void testBeforeClass() {
System.out.println("beforeClass");
}
// 标注到 static 方法上,在该test类中的test方法执行之后执行,多个test方法执行只执行一次
@AfterClass
public static void testAfterClass() {
System.out.println("testAfterClass");
}
// 断言 junit 框架
@Test
public void test01() {
System.out.println("test01...");
// 写一些断言
Assert.assertEquals("1", "1");
}
Junit Test Assert
使用junit 断言
代码示例
// 断言 junit 框架
@Test
public void test01() {
System.out.println("test01...");
//
Assert.assertEquals("1", "1");
Assert.assertEquals("预期的和实际的不相符", "1", "12");
Assert.assertNotNull(new Object());
Assert.assertNull(null);
Assert.assertTrue(true);
Assert.assertFalse(false);
// 断言预期值 是否满足某些匹配条件, 这里使用了hamcrest
// Assert.assertThat(1, Matchers.greaterThan(0));
}
junit 断言提供了一些常规的 assert ,进行预期值和实际值的匹配以及异常信息指定
hamcrest Assert
hamcrest 相对能进行更多的模式匹配 Matchers
代码示例
// 断言 hamcrest 框架, 模式匹配
@Test
public void test02() {
System.out.println("test02...");
MatcherAssert.assertThat(0, Matchers.equalTo(0));
MatcherAssert.assertThat("预期的值应该和输入值相等", 0, Matchers.equalTo(0));
MatcherAssert.assertThat(0, Matchers.allOf(Matchers.greaterThanOrEqualTo(0), Matchers.notNullValue()));
}
AssertJ Assert
AssertJ 是一种可进行流式断言风格的断言框架
代码示例
// 流式断言 AssertJ
@Test
public void test03() {
Assertions.assertThat(0)
.isGreaterThan(-1)
.isBetween(-100, 100)
.isNotNull();
}
Mockito
mock 可以模拟各个未实现或未完成的方法来指定应该返回什么值;特别测试联调的时候依赖其他服务 造成流程不通时使用。
代码示例
@Test
public void testMock() {
// mock 一个对象
TestService mock = Mockito.mock(TestService.class);
// 模拟 TestServiceMock方法 当传入aaa 的时候输出5
Mockito.when(mock.strLength("aaa")).thenReturn(5) // 第一次返回5
.thenReturn(2) // 第二次调用返回2
.thenReturn(1) // 第三次调用 返回1
.then( invocation -> { // 第四次调用 通过 invocation.callRealMethod()调用真实方法返回值
System.out.println("调用真实方法返回值 = " + invocation.callRealMethod());
return invocation.callRealMethod(); })
.thenThrow(new RuntimeException("调用超过4次")); // 超过4次后报错
//
for (int i = 0; i < 4; i++) {
System.out.println(mock.strLength("aaa")); // 返回3
}
System.out.println(mock.strLength("a")); // 其他都是 0
// 模拟真实的对象调用返回值
Integer spyMockLength = Mockito.spy(TestService.class).strLength("234234234234");
System.out.println(spyMockLength);
// 验证 mock 模拟调用了TestService.strLength 方法几次
Mockito.verify(mock, Mockito.times(4));
// 重置mock
Mockito.reset(mock);
}
json Assert
验证json 是否一致
// json assert; 验证json 数据是否匹配
@Test
public void testJsonAssert() throws JSONException, JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Integer> testMap = new HashMap<>();
testMap.put("a",1);
testMap.put("b",2);
JSONAssert.assertEquals( objectMapper.writeValueAsString(testMap), "{\"a\":2,\"b\":2}", true);
}
JsonPath
解析json 可以通过jsonPth 规定的方式获取响应的json值
代码示例
// json path 详细规则参考:https://github.com/json-path/JsonPath
// 可以获取json中的值进行验证
@Test
public void testJsonPath() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Integer> testMap = new HashMap<>();
testMap.put("a",1);
testMap.put("b",2);
Object aValue = JsonPath.read(objectMapper.writeValueAsString(testMap), "$.a");
System.out.println(aValue);
}
以上简述了 在junit中常用的一些框架
spring Test 在springboot项目中使用 Test
使用spring test 可以模拟在spring环境中进行测试用例的编写。
首先需要加入 springboot test 以来
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
测试类加入注解:
@SpringBootTest(classes = {StartApplication.class}) classes 指定资源类,一般就是springboot 启动类
@RunWith(SpringRunner.class) 运行在什么环境
加入这两个注解 我们启动测试的时候就是一个spring的环境
示例
@SpringBootTest(classes = {StartApplication.class})
@RunWith(SpringRunner.class)
public class SpringTest {
@Autowired
private TestService testService;
@Test
public void testStr() throws Exception {
Assert.assertEquals(testService.strLength("123"), Integer.valueOf(3));
}
我们可以通过@Autowired 自动注入spring bean ; TestService 是被@Service 标注的
Spring Mock
更多的时候我们可能会测试controller ;频繁的启动重启项目也不太合适;所以我们可以使用mock进行模拟
- 添加注解 @AutoConfigureMockMvc
@AutoConfigureMockMvc
public class SpringTest {
- 编写controller
@RestController
@RequestMapping("test")
public class TestController {
@GetMapping
public String strToUp(String str) throws Exception {
return str.toUpperCase();
}
@PostMapping
public Map<String, Object> postMap(@RequestBody Map<String, Object> param) throws Exception {
System.out.println("param = " + param);
Map<String ,Object> newParam = new HashMap<>();
param.forEach((k,v) -> {
newParam.put(k.toUpperCase(), v);
newParam.put(k.toUpperCase(), v);
});
return newParam;
}
}
mock 模拟调用TestController 中的方法
3. 代码示例
mock get请求
@Test
public void testControllerGet() throws Exception {
MvcResult mvcResult
= mockMvc.perform(MockMvcRequestBuilders.get("/test")
.param("str", "param") // 设置请求参数
.contentType(MediaType.APPLICATION_JSON_UTF8) // contentType
.accept(MediaType.APPLICATION_JSON_UTF8)) // 接收的contentType
.andExpect(ResultMatcher.matchAll( // 预期
status().isOk())) // 预期httpStatus 是ok 200 的
.andDo(print()) // 打印相关信息
.andReturn();
}
mock post请求
@Test
public void testControllerPost() throws Exception {
Map<String, Object> param = new HashMap<>();
param.put("p1","v1");
param.put("p2", "v2");
ObjectMapper objectMapper = new ObjectMapper();
mockMvc.perform( // 请求信息
post("/test")
.characterEncoding(StandardCharsets.UTF_8.name())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(param)))
.andExpect( // 断言
ResultMatcher.matchAll(
// httpStatus 是否是200
status().isOk(),
// 断言 content-type
content().contentType(MediaType.APPLICATION_JSON_UTF8),
// 返回值转换为json 和输入的 值转换为json 他们相同
content().json(objectMapper.writeValueAsString(param)),
// 解析json,提取json数据中的变量是否和预期的value一致
jsonPath("$.P1").value("v1")))
.andDo(print()); // 执行一些后续操作
}