单元测试

单元测试

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。在Java中单元测试的最小单元是类。

为什么写单元测试?

  1. 保证或验证实现功能。
  2. 保护已经实现的功能不被破坏。

只针对某一个功能点写测试,比如独立测试某类中的某个方法。但这个类和方法本身不是独立的,可能会去调用其他的类或方法。我们可以采用Mockito和PowerMock两种工具,来虚拟那些外部的、不容易构造的对象:

  1. Mockito:适用于大多数标准的单元测试。

  2. PowerMock

    • PowerMock在Mockito的基础上,额外增加了更多case(如static Method,final method, 枚举类, private method和Constructor)
    • PowerMock写法与Mockito基本相同,这是因为PowerMock是从Mockito的一个特殊的API衍化而来。比如当添加PowerMock Junit-module的maven依赖时时,其实还要导入Mockito-API。
1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
</dependency>

Mockito

通过创建mock或spy对象,并制定具体返回规则来实现模拟的功能:

  1. mock对象对于未指定处理规则的调用,会按方法返回值类型返回该类型的默认值(如int、long则返回0,boolean则返回false,对象则返回null,void则什么都不做)
  2. spy对象在未指定处理规则时则会直接调用真实方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class OpenServiceImplTest {
// @InjectMocks真正需要被测试的类
@InjectMocks
private final IOpenService openService = new OpenServiceImpl();

// @Mock创建虚拟对象(外部类等)
@Mock
private IOpenWorkOrderDao openWorkOrderDao;

@Mock
private ITunnelService tunnelService;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void getOpenDetailTest() {
final int id = 321;
final OpenWorkOrderEntity openWorkOrderEntity = new OpenWorkOrderEntity() {{
this.setId(id);
this.setWorkOrderNo("12");
this.setCustomName("tom");
this.setApnType(1);
}};

// mock的发生时机是当程序执行至”when-method-call-then-return”之类的语句时,可以测试类的逻辑流程
Mockito.when(openWorkOrderDao.selectOpenWorkOrderById(anyInt())).thenReturn(openWorkOrderEntity);
Mockito.doNothing().when(tunnelService).getTunnelInfo(any(OpenDetailDto.class), anyInt(), anyInt());

final OpenDetailDto openDetailDtoResult = openService.getOpenDetail(id);
// Assertions.assertThat(openDetailDtoResult.getId()).isEqualTo(321);
Assertions.assertThat(openDetailDtoResult)
.extracting("id", "workOrderNo", "customName", "apnType")
.contains(
321, "12", "name", 1
);
}

PowerMock

1
@RunWith(PowerMockRunner.class)

Spring Boot

SpringBoot也是基于Junit进行单位测试的。

spring-boot-starter-test这个依赖中包含了:

  • JUnit:Java 应用程序单元测试标准类库。
  • Spring Test & Spring Boot Test:Spring Boot 应用程序功能集成化测试支持。
  • Mockito:一个Java Mock测试框架。
  • AssertJ:一个轻量级的断言类库。
  • Hamcrest:一个对象匹配器类库。
  • JSONassert:一个用于JSON的断言库。
  • JsonPath:一个JSON操作类库。
1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

打开IDEA,在任意类名、任意接口名上,按ctrl+shift+t,选择Create New Test。然后根据提示操作(默认即可),点击确认,就在项目的/test/java下的对应包里,生成了与类对应的测试类。

image-20210513110038208

或者,在任意类名、任意接口名上,按Alt+Insert,然后选择Test。然后根据提示操作(默认即可),点击确认,就在项目的/test/java下的对应包里,生成了与类对应的测试类。

image-20210513125151127

如果没有“Create New Test”,请更新idea版本或者在plugin中安装插件JUnitGenerator V2.0(仅支持到JUNIT4、3等老版本。idea升级后新版本不需要安装此插件)。

参阅:Spring Boot:快速创建单元测试_e6486883的博客-CSDN博客_springboot创建测试单元

image-20210513110528189

代码覆盖率测试工具

Intellij IDEA集成了三种分析单元测试覆盖率的工具,包括IntelliJ IDEA、JaCoCo和Emma。

  1. IntelliJ IDEA,是idea默认自带的插件,统计出来的覆盖率只包含classes、method、line,不详细
  2. JaCoCo,最常用。需要首先在Idea中选择JaCoCo模式,而后在项目的maven polm文件中进行依赖配置。
IntelliJ IDEA使用步骤
  1. Run → Edit Configurations

  2. 选择测试范围:指定要测试的包路径或类文件等

image-20210513135536067

  1. Code Coverage选项卡可以调整覆盖率设置。
    • Tracing mode模式会增加消耗,但测量会更精确。
    • 可以设置记录覆盖信息的类或包,即最后生成的测试覆盖率报告里包含了哪些类或包。

image-20210513135742771

  1. 右键选择Run 'All Tests' with Coverage,开始运行所有测试用例。运行完后,IDE将会在Coverage工具窗显示所有include进来的包/类的覆盖率数据,也可以导出测试覆盖率报告 。
  • 红色方块:没有覆盖(在这一行中没有分支被执行)
  • 黄色方块:部分覆盖(这一行的分支中只有一部分被执行)
  • 绿色方块:完全覆盖(这一行的所有分支都被执行)

image-20210513140508548

JaCoCo使用步骤
  1. Run → Edit Configurations中设置为JaCoCo

image-20210513135742771

  1. maven配置

添加依赖:配置JaCoCo插件一定注意和JDK版本的对应关系,如果是jdk1.8,则插件一定要用最新版,不然会报错误。g’g

1
2
3
4
5
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
</dependency>

配置plugins

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<configuration>
<destFile>target/coverage-reports/jacoco-unit.exec</destFile>
<dataFile>target/coverage-reports/jacoco-unit.exec</dataFile>
<includes>
<include>**/service/**</include>
<include>**/controller/**</include>
<!--<include>**/service/impl/*.class</include>-->
</includes>

<!-- rules里面指定覆盖规则,在覆盖率不满足的情况下,mvn install会报错Build Failure -->
<rules>
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>BUNDLE</element>
<limits>
<!-- 指定方法覆盖到50% -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>METHOD</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>

<!-- 指定分支覆盖到50% -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>

<!-- 指定类覆盖到100%,不能遗失任何类 -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>CLASS</counter>
<value>MISSEDCOUNT</value>
<maximum>0</maximum>
</limit>
</limits>
</rule>
</rules>
</configuration>
<executions>
<execution>
<!--在maven的initialize阶段,将Jacoco的runtime agent作为VM的一个参数传给被测程序,用于监控JVM中的调用。-->
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>

<!--这个check:对代码进行检测,控制项目构建成功还是失败-->
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
</execution>

<!--report:对代码进行检测,然后生成index.html在 target/site/index.html中可以查看检测的详细结果-->
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<!--<phase>test</phase>写上test的时候会自动出现site文件夹,而不需执行下面的jacoco:report步骤,推荐-->
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

刷新maven,会发现多了一个插件:

image-20210513144223695

arget文件夹中会多出一个site文件夹(如果没有点击上述jacoco:report)。点击里面的index.html文件,用浏览器打开即可看到测试报告。

image-20210513144313023

  1. maven配置

执行mvn install 或者 mvn test 命令,获得 JaCoCo的统计数据。执行完以后,target/site/jacoco/目录下会生成一个index.html文件,这是统计数据总览页面,可以在浏览器打开查看。

集成多模块报告

执行 mvn clean package(clean install)命令后,在项目的 ROOT\target\site\目录会生成 jacoco目录

断言

Assert

  • Assert.assertEquals 对比两个值相等
  • Assert.assertNotEquals 对比两个值不相等
  • Assert.assertSame 对比两个对象的引用相等
  • Assert.assertArrayEquals 对比两个数组相等
  • Assert.assertTrue 验证返回是否为真
  • Assert.assertFlase 验证返回是否为假
  • Assert.assertNull 验证null
  • Assert.assertNotNull 验证非null

Assertions

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

「译」JUnit 5 系列:基础入门 - Linesh 林从羽 - OSCHINA - 中文开源技术交流社区

JUnit 单元测试断言推荐 AssertJ - 星朝 - 博客园 (cnblogs.com)

走进Java接口测试之流式断言库AssertJ_Mo小泽的技术博客-CSDN博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import org.assertj.core.api.Assertions;

// 基本数据类型
Assertions.assertThat(result).isEqualTo(123456);

// 对象
Assertions.assertThat(openDetailDtoResult)
.extracting("id", "workOrderNo", "customName", "apnType")
.contains(
321, "12", "集团客户", 1
);
// 数组
Assertions.assertThat(listDto.getDataList())
.isNotEmpty()
.hasSize(2)
.extracting("id", "workOrderNo")
.contains(tuple(1, "first"), tuple(2, "second"));

// Map
Assertions.assertThat(queryParamsMap)
.hasSize(2)
.containsKeys("name", "age")
.contains(
entry("name", "nice"),
entry("age", "23")
);

Collections.singletonList("23")这个方法主要用于只有一个元素的优化,减少内存分配,无需分配额外的内存,可以从SingletonList内部类看得出来,由于只有一个element,因此可以做到内存分配最小化,相比之下ArrayList的DEFAULT_CAPACITY=10个。
1
2
3
4
5
6
7
8
9
10
public static String getRespErrorMessage(ReturnMessage<?> returnMessage) {
if (returnMessage == null) {
return StringUtils.EMPTY;
}
如果returnMessage.getErrorMessage()不为空,则返回returnMessage.getErrorMessage()
否则returnMessage.getErrorCode()不为空,则返回returnMessage.getErrorCode(),否则返回空
return Optional.ofNullable(returnMessage.getErrorMessage())//有errorMessage,返回之
.orElseGet(() -> Optional.ofNullable(returnMessage.getErrorCode())//否则返回errorCode
.orElse(StringUtils.EMPTY));//二者均为null,返回空字符串
}
1
2
3
4
5
6
7
8
9
10
Expected :java.util.Arrays$ArrayList<[SimpleResolver [/8.8.8.8:53], SimpleResolver [/114.114.114.114:53]]>
Actual :java.util.ArrayList<[SimpleResolver [/8.8.8.8:53], SimpleResolver [/114.114.114.114:53]]>

Arrays.asList():得到的类型是java.util.Arrays$ArrayList,而非java.util.ArrayList

使用Arrays.asList()的原因无非是想将数组或一些元素转为集合,而你得到的集合并不一定是你想要的那个集合。

而一开始asList的设计时用于打印数组而设计的,但jdk1.5开始,有了另一个比较更方便的打印函数Arrays.toString(),于是打印不再使用asList(),而asList()恰巧可用于将数组转为集合。

isEqualTo()比较引用地址,所以不相等,对象时使用isEqualToComparingFieldByFieldRecursively

https://blog.csdn.net/qq_34802416/article/details/84192236

1
2
import org.junit.Test;
而不是别的

私有方法

1
2
3
4
5
6
7
8
9
10
11
12
@RunWith(PowerMockRunner.class)
class ExportUtilTest {

@Test
void setRequestId() throws Exception {
ReturnMessage returnMessage = new ReturnMessage();

ReturnMsgUtil returnMsgUtil = new ReturnMsgUtil();
Whitebox.invokeMethod(returnMsgUtil, "setRequestId", returnMessage);
Assertions.assertThat(returnMessage.getRequestId()).doesNotContain("-").hasSize(32);
}
}

私有属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RunWith(PowerMockRunner.class)
public class TldCacheTest {
@InjectMocks
private TldCache tldCache;

@Test
public void isSupportedTldTest() throws IllegalAccessException {
// 模拟私有属性
MemberModifier
.field(TldCache.class, "tldSet")
.set(tldCache, new HashSet<>(Arrays.asList("cn", "com", "us")));
Boolean isSupported = tldCache.isSupportedTld("cn");
Assertions.assertThat(isSupported).isTrue();
}

Set断言

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void getIdSetByPackage() throws IllegalAccessException {
final HashMap<PackageType, Set<String>> typeToIdMap = new HashMap<>();

typeToIdMap.put(PackageType.STANDARD, new HashSet<>(Arrays.asList("0", "3=1")));

MemberModifier
.field(LineCache.class, "typeToIdMap")
.set(lineCache, typeToIdMap);

Assertions.assertThat(lineCache.getIdSetByPackage(PackageType.STANDARD))
.hasSize(2).contains("0", "3=1");
}

Junit常用注解说明

  • @BeforeClass 加上这个注解,则该方法会第一个执行(在所有方法中),且方法要加上关键词static,是一个static方法
  • @Before 带上@Test的方法执行前会执行该方法
  • @Test 加在待测试的方法前面,@Test(timeout = 1000)设置1000毫秒后超时
  • @After 带上@Test的方法执行完毕后会执行该方法
  • @AfterClass 加上这个注解,则该方法最后一个执行(在所有方法中),同样,方法要加上关键词static,是一个static方法

一个单元测试类执行顺序为:

@BeforeClass -> @Before -> @Test -> @After -> @AfterClass

单元测试之使用H2 Database模拟数据库环境 单元测试之使用H2 Database模拟数据库环境 | Coderec’s Blog

SQL Grammar (h2database.com)

单元测试之Mockito与PowerMock https://www.jianshu.com/p/51930cc5dcf9

https://blog.csdn.net/qisibajie/article/details/79068086

https://juejin.cn/post/6844903711483887623

Mockito与PowerMock的使用基础教程

https://juejin.cn/post/6844903711483887623

WEB测试

在Spring Boot项目里面可以直接使用JUnit对web项目进行测试,Spring 提供了“TestRestTemplate”对象,使用这个对象可以很方便的进行模拟请求。

Web测试只需要进行两步操作:

  1. 在@SpringBootTest注解上设置“ebEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT”随机端口;
  2. 使用TestRestTemplate进行post或get请求;

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void getName() {
String name = restTemplate.getForObject("/name", String.class);
System.out.println(name);
Assert.assertEquals("Adam", name);
}
}

其中getForObject的含义代表执行get请求,并返回Object结果,第二个参数设置返回结果为String类型,更多的请求方法:

  • getForEntity:Get请求,返回实体对象(可以是集合);
  • postForEntity:Post请求,返回实体对象(可以是集合);
  • postForObject:Post请求,返回对象;

数据库测试

测试数据操作时,如果给测试类上添加@Transactional,会让数据操作都在内存中完成,并不会真正的commit到数据库,将数据持久化操作截断。

  1. 好处是:既可以测试数据操作方法,又不会污染数据库。
  2. 注意点是:数据持久化的过程不再真实,没有了commit的过程。从而会导致——
    • 无法保证 Entity 之间关联关系,唯一索引和主外键关联的准确性。
    • 无法保证 Entity 创建时间、更新时间和版本化(乐观锁)的赋值逻辑的准确性。
    • 无法保证 Entity 中有 @Transient 注解的属性的赋值逻辑的准确性。
    • 测试的数据不是真实场景存在的问题。
    • 测试中,单个事务中的准备数据,无法在多线程中共享。
1
2
3
4
5
6
7
8
9
10
11
@Test
@Transactional
public void saveTest() {
User user = new User();
user.setName("Adam");
user.setAge(19);
user.setPwd("123456");
userRepository.save(user);
System.out.println("userId:" + user.getId());
Assert.assertTrue(user.getId()>0);
}

集成测试

  1. 集成多个功能
  2. 加载 spring 框架,要启整个 Spring

1.在class上加入@SpringBootTest 和@RunWith(SpringRunner.class)两个注解即可。

  • @SpringBootTest:获取启动类,加载配置,寻找主配置启动类(被 @SpringBootApplication 注解的类)
  • @RunWith(SpringRunner.class):让JUnit运行Spring的测试环境,获得Spring环境的上下文的支持
1
2
3
RunWith(SpringRunner.class)
@SpringBootTest
public class Test() {}

增加@Transactional支持回滚

1
2
3
4
RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class Test() {}

增加@Transactional支持回滚的同时,单独设置方法不回滚(正常提交)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class Test() {

// @Transactional的前提下,实现真正提交事务(即指定@Rollback(false))
@Test
@Rollback(false)
void testCommit(){}

// @Transactional的前提下,默认会回滚(即@Rollback(True))
@Test
void testRollBack(){}
}

2.在测试方法上加上@Test注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@SpringBootTest
@RunWith(SpringRunner::class)
@Transactional
class UserServiceImplTest {
@Autowired
private lateinit var userServiceImpl: UserServiceImpl
private var userId = "CIDC-U-cd8e01a325ea4eb0bcf0b83f973d5d9f"

@Before
fun setUp() {
AuthUserContext.setAuthUser(RequestUser(userId))
}

@Test
fun getUserInfoById() {
val result = userServiceImpl.getUserInfoById(this.userId)
assertNotNull(result)
}
}

测试私有方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class Test {

@Autowired
private Service service;

@Test
public void test() throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
// 获取class
Class<? extends Service> clazz = service.getClass();
// 获取方法,注意param的类型
Method myPricateMothod= clazz.getDeclaredMethod("myPricateMothod", String.class);
myPricateMothod.setAccessible(true);
// 执行这个service,不要使用clazz.newInstance(),这个方法是新new一个对象
myPricateMothod.invoke(service, "myparam");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
val targetClass = DomainServiceImpl::class.java
val method: Method = targetClass.getDeclaredMethod(
"createDomainInVendorWrapper",
DomainCreation::class.javaObjectType,
Vendor::class.javaObjectType
) //获得method.注意,这里不能使用getMethod方法,因为这个方法只能获取public修饰的方法..
method.setAccessible(true)

val operatorServiceField: Field = targetClass.getDeclaredField("operatorService")
operatorServiceField.setAccessible(true)
operatorServiceField.set(domainService, operatorService)

val instanceServiceField: Field = targetClass.getDeclaredField("instanceService")
instanceServiceField.setAccessible(true)
instanceServiceField.set(domainService, instanceService)

val operateResult: Any = method.invoke(
domainService,
DomainCreation("abc.com", "unit test", instancePO.instanceId),
Vendor.DNS_POD
)

ReflectionUtilsSpring中一个常用的类,属于spring-core包;

ReflectionTestUtils则属于spring-test包。

两者功能有重叠的地方,而ReflectionUtils会更强大。在单元测试时使用ReflectionTestUtils,能增加我们的便利性。

处理

UT中使用ReflectionTestUtils.setField不能mock掉依赖问题解决_苦行僧-CSDN博客_reflectiontestutils.setfield

service - ReflectionTestUtils not working with @Autowired in Spring Test - Stack Overflow

获取对象的成员变量:

1
public static Object getField(@Nullable Object targetObject, String name)

给对象注入成员变量:

1
public static void setField(Class<?> targetClass, String name, @Nullable Object value)

调用成员方法:

1
public static <T> T invokeMethod(Object target, String name, Object... args)

image-20210524162554542

单元测试时测试一个private私有方法时,我们第一想法可能是用java反射机制。


Method method = clazz.getDeclaredMethod(methodName, classes)
method.setAccessible(true);
method.invoke(obj, objects)

Spring 有一个好用的测试工具类ReflectionTestUtils


ReflectionTestUtils.invokeMethod(Object target, String name, Object… args)

即可完成调用私有方法。

maven依赖:


org.springframework
spring-test
4.1.6.RELEASE
test

————————————————
版权声明:本文为CSDN博主「lijie2049」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lijie2049/article/details/84732723

1
Unexpected exception, expected<exception.DomainException> but was<java.lang.reflect.InvocationTargetException>

反射,异常处理

What Causes java.lang.reflect.InvocationTargetException? | Baeldung

1
2
3
4
5
6
7
8
9
10
val targetClass = DomainServiceImpl::class.java
val method: Method = targetClass.getDeclaredMethod(
"handleExitedParentsDomainName",
String::class.java
)
method.setAccessible(true)
val exception: Exception = assertThrows(InvocationTargetException::class.java) {
method.invoke(domainService, domainName)
}
Assertions.assertThat(exception.cause!!.javaClass).isEqualTo(DomainException::class.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    private fun getSubDomainPOList(domainName: String, withUser: Boolean, userId: String? = null): List<DomainPO>? 

val method: Method = targetClass.getDeclaredMethod(
"getSubDomainPOList",
String::class.java,
Boolean::class.java,
String::class.java
)


private fun getDomainListByInstanceId(
instanceId: String, withUser: Boolean? = null, userId: String? = null
): List<DomainPO>
val method: Method = targetClass.getDeclaredMethod(
"getDomainListByInstanceId",
String::class.java,
Boolean::class.javaObjectType,
String::class.java
)

Java类型与Kotlin类型对应关系_WongKyunban的博客-CSDN博客

MockMvc是由spring-test包提供,实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,使得测试速度快、不依赖网络环境。同时提供了一套验证的工具,结果的验证十分方便。

(1) mockMvc.perform执行一个请求。

(2) MockMvcRequestBuilders.get(“XXX”)构造一个请求。

(3) ResultActions.param添加请求传值

(4) ResultActions.accept()设置返回类型

(5) ResultActions.andExpect添加执行完成后的断言。

(6) ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如处使用print()输出整个响应结果信息。

(7) ResultActions.andReturn表示执行完成后返回相应的结果。

-------------Keep It Simple Stupid-------------
0%