赞
踩
Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库;在 Spring Boot 2.2.0 版本之前,spring-boot-starter-test 包含了 JUnit 4 的依赖;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
mvn test
表明在所有测试方法执行之前执行的方法,且只执行一次
表明在所有测试方法执行之后执行的方法,且只执行一次
表明在每个测试方法执行之前都会执行的方法
表明在每个测试方法执行之后都会执行的风发
通过select来创建套件,通过包、类、和方法三个维度来选择需要执行的测试用例。所有条件是且的关系,求的是交集。
使用classname进行匹配时,需要加上所在的包名(唉~ 好麻烦)
若交集为空,如下图效果:
若交集不为空,则执行匹配的用例:
新建一个类TestRunWithDemo.java--.>作用就是制定哪些测试类,哪些测试方法运行跑测试案例
注解 说明
|- @valueSource -| 通过注解可以直接指定携带的运行参数 |
| @EnumSource | 枚举参数元,允许我们通过将参数值有给定的Enum枚举类型传 |
| @MethodSource | 通过其他的Java方法函数来作为参数源 |
| @ArgumentSource | 参数类参数源,应用类必须实现ArgumentsProvide接口 |
| @CSVSource | csv格式作为参数源 |
| @CSVFileSource | csv文件作为参数源 |
以上是Junit5的参数化方式,在这里我就不一一介绍了,本人用的更多的MethodSource+yaml的参数化方式;因为yaml文档能够比较清晰地定义各种类型的参数,结合MethodSource注解就能够很方便的构建出不同类型的参数
简单的MethodSource实例
// 添加成员@ParameterizedTest
@MethodSource("testData")
public void successTest(String name,String phone) {
System.out.println("name: " + name +"phone: " + phone)
}
// 返回用例数据
public static Stream<Arguments> testData() {
return Stream.of(
Arguments.arguments("周杰伦","12121221211"),
Arguments.arguments("林俊杰","12121221212"),
Arguments.arguments("王力宏","12121221213"));
}
上面试Junit5自带的断言方式,如果需要更复杂的断言可以使用hamcrest断言方式;
软断言:如果一个用例需要进行多次断言,就需要用到assertAll(需要先设置java8语法),使用软断言后不会因为一个断言的失败报错而中断测试
软断言实例:
@Test void addTest(){ assertAll( ()->assertEquals(9==9), ()->assertEquals(7==2), ()->assertEquals(10==10) ); } // 二:现将assert可执行语句进行储存,再用assertAll进行断言 ArrayList<Executable> assertList = new ArrayList<>(); for(int i = 0;i<3;i++){ int result = 1 + i; assertList.add({ // 先将断言语句存起来 () -> assertEquals(3,result); }) } assertAll(assertList.Stream());
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import static java.lang.Thread.sleep; class TimeoutExampleTest { @Test @Timeout(7) void timeoutDemo1() throws InterruptedException { sleep(10000); System.out.println("超时用例1"); } @Test void timeoutDemo2(){ System.out.println("超时用例2"); } }
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import static java.lang.Thread.sleep; class TimeoutExampleTest { @AfterEach @Timeout(3) void teardown() throws InterruptedException { sleep(40000); System.out.println("结束测试"); } @BeforeEach @Timeout(3) void setup() throws InterruptedException { sleep(40000); System.out.println("开始测试"); } @Test void timeoutDemo2(){ System.out.println("超时用例2"); } }
测试用例有业务逻辑相关
集成测试(主流程测试)
类型 说明
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; //设定排序方法为注解指定排序 @TestMethodOrder(OrderAnnotation.class) class OrderedTestsDemo { @Test @Order(1) void nullValues() { } @Test @Order(2) void emptyValues() { } @Test @Order(3) void validValues() { } }
package com.hogwarts.JUnit5; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; //根据DisplayName进行排序 @TestMethodOrder(MethodOrderer.DisplayName.class) class orderExampleTest { @Test @DisplayName("a用例") void firstCase() { System.out.println("第一条用例"); } @Test @DisplayName("b用例") void secondCase() { System.out.println("第二条用例"); } @Test @DisplayName("c用例") void thirdCase() { System.out.println("第三条用例"); } }
package com.hogwarts.JUnit5; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; // 设置排序类型为方法排序 @TestMethodOrder(MethodOrderer.MethodName.class) class orderExampleTest { @Test void bCase() { System.out.println("第二条用例"); } @Test void aCase() { System.out.println("第一条用例"); } @Test void cCase() { System.out.println("第三条用例"); } }
package com.hogwarts.JUnit5; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; //设计排序类型为随机排序 @TestMethodOrder(MethodOrderer.Random.class) class orderExampleTest { @Test void firstCase() { System.out.println("第一条用例"); } @Test void secondCase() { System.out.println("第二条用例"); } @Test void thirdCase() { System.out.println("第三条用例"); } }
package com.hogwarts.JUnit5; import org.junit.jupiter.api.*; // 指定类执行顺序的方式,DisplayName表示通过DisplayName排序 @TestClassOrder(ClassOrderer.DisplayName.class) class orderExampleTest { // 因为是多类执行,所以需要结合@Nested注解 @Nested @DisplayName("b") class PrimaryTests { @Test void test1() { System.out.println("第一条用例"); } } @Nested @DisplayName("a") class SecondaryTests { @Test void test2() { System.out.println("第二条用例"); } } }
import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestClassOrder; // 指定类执行顺序的方式,OrderAnnotation表示通过order注解排序 @TestClassOrder(ClassOrderer.OrderAnnotation.class) class OrderedNestedTestClassesDemo { @Nested @Order(1) class PrimaryTests { @Test void test1() { } } @Nested @Order(2) class SecondaryTests { @Test void test2() { } } }
package com.hogwarts.JUnit5; import org.junit.jupiter.api.*; // 指定类执行顺序的方式,ClassName代表指定为类名排序 @TestClassOrder(ClassOrderer.ClassName.class) class orderExampleTest { // 因为是多类执行,所以需要结合@Nested注解 @Nested class PrimaryTests { @Test void test1() { System.out.println("第一条用例"); } } @Nested class SecondaryTests { @Test void test2() { System.out.println("第二条用例"); } } @Nested class ThirdTests { @Test void test2() { System.out.println("第三条用例"); } } }
#默认排序方式为随机排序
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$Random
#默认排序方式为通过方法名排序
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$MethodName
#默认排序方式为通过Order注解指定
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$OrderAnnotation
#默认排序方式为通过DisplayName排序
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$DisplayName
#默认排序方式为随机排序
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$Random
#默认排序方式为通过类名排序
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$ClassName
#默认排序方式为通过DisplayName排序
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$DisplayName
#默认排序方式为通过Order注解指定
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$OrderAnnotation
<dependencies> <!--导入Mockito单元测试依赖--> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> <!--导入junit单元测试依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies>
1.postman里新建多线程集合组
2.将"目标访问地址"添加进新新线程组
3.Run运行Collection
大批量线程高并发访问B,导致A失效了
简述使用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
//"其中,SpringRunner继承自SpringJUnit4ClassRunner,使用哪一个Spring提供的测试测试引擎都可以"-->作用就是告示当前测试类我所使用的测试工具是谁?是"SpringRunner" @RunWith(SpringRunner.class) //"@SpringBootTest的属性指定的是引导类的字节码对象"-->用于启指向"主启动类"是谁,帮助你启动项目 @SpringBootTest(classes = MySpringBootApplication.class) public class MapperTest { @Autowired private UserMapper userMapper; @Resource private UserService userService; @Test public void test() { List<User> users = userMapper.queryUserList(); System.out.println(users); } }
@SpringBootTest class Test { @Autowired private WebApplicationContext webApplicationContext; //mvc 环境对象 private MockMvc mockMvc; @BeforeEach public void init() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } @Test void getXhCreateTaskRecord() throws Exception { // mvc = MockMvcBuilders.webAppContextSetup(wac).build(); final String json = "{}"; final MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post("/getXhCreateTaskRecord") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON_VALUE) //传json参数 .content(json); final String contentAsString = mockMvc.perform(request).andReturn().getResponse().getContentAsString(); log.info(contentAsString); } } "可以直接这样,不用使用 http://ip:port 了,这样测试更方便"
//配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用
@Transactional
@Rollback
public class Test {
}
上面两句的作用是,让我们对数据库的操作会事务回滚,如对数据库的添加操作,在方法结束之后,会撤销我们对数据库的操作。
为什么要事务回滚?
测试过程对数据库的操作,会产生脏数据,影响我们数据的正确性
不方便循环测试,即假如这次我们将一个记录删除了,下次就无法再进行这个Junit测试了,因为该记录已经删除,将会报错。
如果不使用事务回滚,我们需要在代码中显式的对我们的增删改数据库操作进行恢复,将多很多和测试无关的代码
使用Assert类的静态方法,assertEquals(),包含两个参数,左边是预期值,右边是实际值。当预期值与实际值不同时便会报错。
package com.junit.MyClass; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; /** * Created by lesley on 2017/1/14. */ public class CalculatorTest { //注意这个不能忘记!!要不然后面无法调用 private Calculator calculator; @Before public void setUp() throws Exception { calculator = new Calculator(); } @Test public void add() throws Exception { assertEquals(calculator.add(3, 5),8); } }
package com.teachertom.test; import com.teachertom.calculator.Calculator; import org.junit.Assert; import org.junit.Test; public class CalculatorTest { @Test public void testAdd(){ Calculator calculator=new Calculator(); Assert.assertEquals(10,calculator.add(5,5)); } @Test public void testSubtract(){ Calculator calculator=new Calculator(); Assert.assertEquals(5,calculator.subtract(10,5)); } }
点击运行,实际值与预期值相符,测试通过。
如果不相符,则会出现下列字样。
2、Junit基本注解介绍 //在所有测试方法前执行一次,一般在其中写上整体初始化的代码 @BeforeClass //在所有测试方法后执行一次,一般在其中写上销毁和释放资源的代码 @AfterClass //在每个测试方法前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据) @Before //在每个测试方法后执行,在方法执行完成后要做的事情 @After // 测试方法执行超过1000毫秒后算超时,测试将失败 @Test(timeout = 1000) // 测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败 @Test(expected = Exception.class) // 执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类 @Ignore("not ready yet") @Test @RunWith 在JUnit中有很多个Runner,他们负责调用你的测试代码,每一个Runner都有各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。 如果我们只是简单的做普通Java测试,不涉及Spring Web项目,你可以省略@RunWith注解,这样系统会自动使用默认Runner来运行你的代码。
正常情况下我们写了5个测试类,我们需要一个一个执行。
打包测试,就是新增一个类,然后将我们写好的其他测试类配置在一起,然后直接运行这个类就达到同时运行其他几个测试的目的。
@RunWith(Suite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {
// 类中不需要编写代码
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。