0


spring boot 单元测试JUnit5使用断言Assertions和假定Assumptions、嵌套、参数测试

spring boot 单元测试JUnit5使用断言Assertions和假定Assumptions、嵌套、参数测试

本文基于spirng boot 2.7.11, 大家注意自己的版本

Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库

SpringBoot 2.4 以上版本移除了默认对 Vintage 的依赖

源码地址:https://gitcode.net/qq_39339588/springboot.git

文章目录

1. 标记单元测试类和方法

@SpringBootTest注解,可以标记为测试类

@Test注解标记是测试方法

@DisplayName注解是标记个名称

@SpringBootTestpublicclassHelloWorldTest{/**
     * 断言基础
     */@Test@DisplayName("简单断言")publicvoidsimple(){}}

2. 断言的简单使用

1)基本类型和对象的断言
/**
* 基本类型和对象的断言
*/@Test@DisplayName("简单断言")publicvoidsimple(){Assertions.assertEquals(3,1+2,"不相等");Assertions.assertNotEquals(3,1+1,"相等了");//断言对象Assertions.assertNotSame(newObject(),newObject(),"对象相同");Object o =newObject();Assertions.assertSame(o, o,"断言不相等了");Assertions.assertFalse(1>2);Assertions.assertTrue(1<2);Assertions.assertNull(null);Assertions.assertNotNull(newObject());}
2)数组断言
@DisplayName("数组断言")@Testpublicvoidarray(){// 断言两个数组对象不相等Assertions.assertNotEquals(newint[]{1,2},newint[]{1,2});}
3)组合断言
@DisplayName("组合断言")@Testpublicvoidall(){// 断言所多个断言方法都正确Assertions.assertAll("组合断言",()->Assertions.assertEquals(2,1+1),()->Assertions.assertTrue(1>0));}
4)异常断言
@DisplayName("异常断言")@Testpublicvoidexception(){// 断言方法 会出现异常ArithmeticException arithmeticException =Assertions.assertThrows(ArithmeticException.class,()->System.out.println(1%0));
    arithmeticException.printStackTrace();}
5)超时断言
@DisplayName("超时断言")@TestpublicvoidtimeOut(){// 断言方法执行不会超过1秒Assertions.assertTimeout(Duration.ofMillis(1000),()->Thread.sleep(500));}
6)快速失败断言
@DisplayName("快速失败")@TestpublicvoidfailFast(){// 触发快速失败后AssertionFailedError ex =Assertions.assertThrows(AssertionFailedError.class,()->{Assertions.fail("触发快速失败");});
    ex.printStackTrace();}

3. 前置条件断言,假设假定

执行断言的前提条件,如果假定成功true,才会去执行

/**
 * 前置条件,假设假定
 */@DisplayName("前置条件")@Testpublicvoidassuming(){String evn ="dev";// 执行断言的前提条件,如果假定成功true,才会去执行下一行,如果假定失败,下边的就不执行了Assumptions.assumeTrue(Objects.equals(evn,"dev"));Assumptions.assumeFalse(Objects.equals(evn,"prod"));System.out.println("dev和不是prod,执行了");Assumptions.assumeTrue(Objects.equals(evn,"dev1"));System.out.println("dev1,这句会忽略,不会执行输出");}/**
 * 假定成功true,才会去执行 执行器方法
 */@DisplayName("前置条件That")@TestpublicvoidassumingThat(){// 假定成功,才会去执行 执行器方法Assumptions.assumingThat(Objects.equals("dev","dev"),()->{System.out.println("in dev");});}

4. 嵌套@Nested

内部嵌套,每次会先走外层的beforeEach,在走内部的beforeEach;支持嵌套的嵌套

@DisplayName("单元测试示例")@SpringBootTestpublicclassHelloWorldTest{Stack<Object> stack;/**
     * 内部嵌套,每次会先走外层的beforeEach,在走内部的beforeEach
     */@DisplayName("内部嵌套测试")@NestedclassInnerTest{@BeforeEachvoidnewStack(){// 创建一个栈对象
            stack =newStack<>();}@DisplayName("检查是否为空")@TestvoidisEmpty(){Assertions.assertTrue(stack.isEmpty());}@DisplayName("抛出一个栈pop异常")@TestvoidthrowExceptionWhenPop(){Assertions.assertThrows(EmptyStackException.class, stack::pop);}@DisplayName("抛出一个栈peek异常")@TestvoidthrowExceptionWhenPeek(){Assertions.assertThrows(EmptyStackException.class, stack::peek);}@Nested@DisplayName("内部的内部嵌套测试")classInnerInnerTest{String item ="item";@BeforeEachvoidpushAnItem(){// 放入一个元素
                stack.push(item);}@DisplayName("不为空了")@TestvoidisNotEmpty(){Assertions.assertFalse(stack.isEmpty());}@DisplayName("取出一个来,用pop")@TestvoidreturnItemByPop(){Assertions.assertEquals(item, stack.pop());Assertions.assertTrue(stack.isEmpty());}@DisplayName("取出一个来,用peek")@TestvoidreturnItemByPeek(){Assertions.assertEquals(item, stack.peek());Assertions.assertFalse(stack.isEmpty());}}}

5. 参数化测试

参数化测试,让单元测试的方法支持接收传入的参数

将可以使用不同的参数进行多次单元测试,有多少套参数,就执行多少次单元测试

而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码

1)@ValueSource注解,基本类型入参
/**
 * @ValueSource:为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
 * @param params
 */@DisplayName("参数化测试,值来源")@ParameterizedTest@ValueSource(strings ={"a","b","c"})publicvoidparameterizedTest(String params){// 会执行3次,分别执行a,b,cSystem.out.println(params);Assertions.assertTrue(StringUtils.isNotBlank(params));}
2)@NullSource注解,null入参
/**
 * null入参
 *
 * @param params
 */@DisplayName("null的入参")@ParameterizedTest@NullSourcepublicvoidtestNull(String params){Assertions.assertNull(params);}
3)@EnumSource注解,枚举入参
/**
 * 枚举入参,会把枚举遍历一遍,分别执行一次方法
 */@DisplayName("枚举的入参")@ParameterizedTest@EnumSource(TestEnum.class)publicvoidtestEnumSource(TestEnum params){System.out.println("state:"+ params.state +",msg:"+ params.msg);// state:1,msg:好// state:2,msg:不好Assertions.assertNotNull(params);}/**
 * 枚举类
 */@Getter@AllArgsConstructorpublicenumTestEnum{GOOD(1,"好"),BAD(2,"不好");int state;String msg;}
4)@CsvSource注解,多参数入参
@DisplayName("参数化测试,@CsvSource")@ParameterizedTest@CsvSource({"a,b,c"})voidparameterizedTestCsvSource(String a,String b,String c){// 默认使用逗号分隔System.out.println(a + b + c);Assertions.assertNotNull(a);}@DisplayName("参数化测试,@CsvSource2")@ParameterizedTest@CsvSource(value ={"a,b,c-D"}, delimiterString ="-")voidparameterizedTestCsvSource2(String abc,String d){// 默认使用逗号分隔,指定分隔符"-"System.out.println(abc);System.out.println(d);Assertions.assertNotNull(abc);// a,b,c// D}
5)@CsvFileSource,参数文件入参

可以把文件中的内容当做参数,批量来执行,下边附带了my.csv和my2.csv文件内容

注意,要在测试目录下,新建resources目录,再放入my.csv和my2.csv文件

/**
 * 参数文件
 *
 * @param methodName
 */@DisplayName("参数化测试,@CsvFileSource")@ParameterizedTest@CsvFileSource(resources ="/my.csv")voidparameterizedTestWithCsvFileSource(String methodName){// 测试目录下,新建resources目录System.out.println(methodName);Assertions.assertNotNull(methodName);}@DisplayName("参数化测试,@CsvFileSource")@ParameterizedTest@CsvFileSource(resources ="/my2.csv", delimiterString ="|")voidparameterizedTestWithCsvFileSource2(String name,Integer age){// 测试目录下,新建resources目录System.out.println(name +":"+ age);Assertions.assertNotNull(name);// a:18// b:17// c:20}

my.csv文件

1
2
3
4

my2.csv

a|18
b|17
c|20
6)@MethodSource注解,方法返回值入参

把一个方法的返回值,作为测试用例方法的参数

/**
 * 动态参数
 */@DisplayName("参数化测试,方法来源")@ParameterizedTest@MethodSource("method1")// 如果不指定方法名称,会去找与自己相同名称的静态方法publicvoidparameterizedTestWithMethodParam(String params){// MethodSource("method1") 接收这个方法的返回值,之后会执行2次,a,bSystem.out.println(params);Assertions.assertNotNull(params);}staticStream<String>method1(){returnStream.of("a","b");}@DisplayName("参数化测试,方法来源,多参数")@ParameterizedTest@MethodSource// 如果不指定方法名称,会去找相同名称的静态方法publicvoidparameterizedTestWithMethodMultipleParams(String name,Integer age){System.out.println(name +":"+ age);// a:18// b:17// c:20Assertions.assertNotNull(name);}staticStream<Arguments>parameterizedTestWithMethodMultipleParams(){returnStream.of(Arguments.arguments("a",18),Arguments.arguments("b",17),Arguments.arguments("c",20));}
7) @ArgumentsSource注解,自定义参数入参
/**
 * 实现ArgumentsProvider接口,并在测试方法上使用@ArgumentsSource注解。
 */@DisplayName("@ArgumentsSource注解")@ParameterizedTest@ArgumentsSource(MyArgumentsProvider.class)publicvoidtestArgumentsSource(String name,int age){System.out.println(name +":"+ age);// aa:18// bb:20// cc:30Assertions.assertNotNull(name);}

本文转载自: https://blog.csdn.net/qq_39339588/article/details/130901703
版权归原作者 Goldchenn 所有, 如有侵权,请联系我们删除。

“spring boot 单元测试JUnit5使用断言Assertions和假定Assumptions、嵌套、参数测试”的评论:

还没有评论