您当前的位置: 首页 >  单元测试

梁云亮

暂无认证

  • 1浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Junit单元测试

梁云亮 发布时间:2020-02-03 10:27:09 ,浏览量:1

Junit单元测试简介 Junit:

我们写好一个方法后经常希望对其单独进行测试,从前我们都是写一个main方法,在main方法中对被测试方法进行调用。这种方式相对麻烦。 Junit是一个测试框架,利用它可以在不写main方法的情况下调用被测试方法,从而对方法中的代码进行测试。

Junit要求:
  • 被测试方法必须为无参数、非静态、无返回值的公共(public)方法。
  • 测试用类必须为public类
测试过程:
  1. 在方法上加上注解:@Test
  2. 导入Junit框架jar包
  3. 在被测试方法上执行Junit测试
Junit5简介

在这里插入图片描述 JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage 其中:

  • JUnit Platform是在JVM上启动测试框架的基础。
  • JUnit Jupiter是JUnit5扩展的新的编程模型和扩展模型,用来编写测试用例。Jupiter子项目为在平台上运行Jupiter的测试提供了一个TestEngine (测试引擎)。
  • JUnit Vintage提供了一个在平台上运行JUnit 3和JUnit 4的TestEngine 。

整个Junit5可以划分成三层:顶层框架(Framework)、中间的引擎(Engine),底层的平台(Platform):

  • Platform:位于架构的最底层,是JVM上执行单元测试的基础平台,还对接了各种IDE(例如IDEA、eclipse),并且还与引擎层对接,定义了引擎层对接的API;整个Junit Platform是开放的,通过引擎API各种测试框架都可以接入;
  • Jupiter:位于引擎层,支持5版本的编程模型、扩展模型;是Junit5的核心,它包含了很多丰富的新特性来使JUnit自动化测试更加方便、功能更加丰富和强大。
  • Vintage:位于引擎层,用于执行低版本的测试用例;是一个对JUnit3,JUnit4兼容的测试引擎,使旧版本junit的自动化测试脚本可以顺畅运行在junit5下,其实也可以看作是基于junit platform实现的接入范例。

注意:JUnit5需要JDK8或以上版本才能支持。JUnit5全面支持JDK8 lambda语法表达。

JUnit5中的Assert方法
  • assertTrue/False([String message,]boolean condition); 判断一个条件是true还是false。其中

    • assertTrue(boolean condition); condition:如果condition结果为true,则通过测试.
    • assertFalse(boolean condition); condition:如果condition结果为false,则通过测试.
  • fail([String message,]); 失败,可以有消息,也可以没有消息。

  • assertEquals([String message,]Object expected,Object actual); 判断是否相等,可以指定输出错误信息。 第一个参数是期望值,第二个参数是实际的值。

  • assertNotEquals([String message,]Object expected,Object actual); 判断是否不相等。 第一个参数是期望值,第二个参数是实际的值。

  • assertArrayEquals([java.lang.String message,] java.lang.Object[] expecteds, java.lang.Object[] actuals) ;

  • assertNotNull/Null([String message,]Object obj); 判读一个对象是否非空(非空)。

  • assertSame/NotSame([String message,]Object expected,Object actual); 判断两个对象是否指向同一个对象。看内存地址。

  • failNotSame/failNotEquals(String message, Object expected, Object actual) 当不指向同一个内存地址或者不相等的时候,输出错误信息。 注意信息是必须的,而且这个输出是格式化过的。

  • assertThat(java.lang.String reason, java.lang.Object actual, org.hamcrest.Matcher matcher); 其中,reason为断言失败时的输出信息,actual为断言的值或对象,matcher为断言的匹配器,里面的逻辑决定了给定的actual对象满不满足断言。 (如果需要是用assertThat需要在项目中引入junit4的jar包,以及hamcrest-core.jar和hamcrest-library.jar)

JUnit4 与 JUnit 5 常用注解对比 JUnit4JUnit5说明@Test@Test表示该方法是一个测试方法。JUnit5与JUnit 4的@Test注解不同的是,它没有声明任何属性,因为JUnit Jupiter中的测试扩展是基于它们自己的专用注解来完成的。这样的方法会被继承,除非它们被覆盖@BeforeClass@BeforeAll表示使用了该注解的方法应该在当前类中所有使用了@Test @RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之前 执行@AfterClass@AfterAll表示使用了该注解的方法应该在当前类中所有使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之后执行@Before@BeforeEach表示使用了该注解的方法应该在当前类中每一个使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之前 执行@After@AfterEach表示使用了该注解的方法应该在当前类中每一个使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之后 执行@Ignore@Disabled用于禁用一个测试类或测试方法@Category@Tag用于声明过滤测试的tags,该注解可以用在方法或类上;类似于TesgNG的测试组或JUnit 4的分类@Parameters@ParameterizedTest表示该方法是一个参数化测试@RunWith@ExtendWith@Runwith就是放在测试类名之前,用来确定这个类怎么运行的@Rule@ExtendWithRule是一组实现了TestRule接口的共享类,提供了验证、监视TestCase和外部资源管理等能力@ClassRule@ExtendWith@ClassRule用于测试类中的静态变量,必须是TestRule接口的实例,且访问修饰符必须为public。

说明:

  • BeforeEach:被该注解修饰的方法会在每个测试方法执行前被执行一次,会被子类继承,取代低版本的Before;
  • AfterEach:被该注解修饰的方法会在每个测试方法执行后被执行一次,会被子类继承,取代低版本的Before;
  • BeforeAll:被该注解修饰的必须是静态方法,会在所有测试方法之前执行,会被子类继承,取代低版本的BeforeClass;
  • AfterAll:被该注解修饰的必须是静态方法,会在所有测试方法执行之后才被执行,会被子类继承,取代低版本的AfterClass;
  • ExtendWith:这是用来取代旧版本中的RunWith注解,不过在SpringBoot环境如果没有特别要求无需额外配置,因为SpringBootTest中已经有了;
  • Test:被该注解修饰的就是测试方法;
  • DisplayName:测试方法的展现名称,在测试框架中展示,支持emoji;
  • Timeout:超时时长,被修饰的方法如果超时则会导致测试不通过;
  • Disabled:不执行的测试方法;

Junit5中对不同测试执行阶段提供了对应的回调接口,使扩展JUnit更加方便:

回调方法描述BeforeAllCallback在@BeforeAll 注解的方法之前执行AfterAllCallback在@AfterAll 注解的方法之后执行BeforeEachCallback在@BeforeEach 注解的方法之前执行AfterEachCallback在@AfterEach 注解的方法之后执行BeforeTestExecutionCallback在测试方法运行之前执行AfterTestExecutionCallback在测试方法运行之后执行 相关Maven依赖

  junit
  junit
  4.12
  test



	org.junit.jupiter
	junit-jupiter
	5.7.2
	test


Junit5示例
import org.junit.jupiter.api.Test;

import java.time.Duration;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import static org.junit.jupiter.api.Assertions.assertTrue;


public class Junit5AssertTest {

    /**
     * assertEquals比较两个值是否相同
     */
    @Test
    void fun1(){
        assertEquals(2, 2);
        //当不相等时,会打印出第三个参数
        assertEquals(4, 5, "不相等");
    }
    /**
     * assertTrue 判断括号里面的参数是否为true
     */
    @Test
    void fun2(){
        assertTrue('a'  assertEquals("RESEARCH", dept.getDname()),
                () -> assertEquals("NEWYORK", dept.getLoc())
        );
    }

    /**
     * assertAll()方法也可以嵌套多个assertAll()方法
     * 其中嵌套的多个测试组,这些组只会打印出这个组和父组的错误,对其他的组没有影响
     */
    @Test
    void dependentAssertions() {
        assertAll("properties",
                //第一个测试组
                () -> {
                    String dname = dept.getDname();
                    assertNotNull(dname);
                    assertAll("dname",
                            () -> assertTrue(dname.startsWith("R")),
                            () -> assertTrue(dname.endsWith("H"))
                    );
                },
                //第二个测试组
                () -> {
                    String loc = dept.getLoc();
                    assertNotNull(loc);
                    assertAll("loc",
                            () -> assertTrue(loc.startsWith("N")),
                            () -> assertTrue(loc.endsWith("k"))
                    );
                }
        );
    }

    /**
     * assertThrows()可以用来判断lambda表达式中的代码抛出的异常
     * 比如下面案例就是测试了抛出异常的信息是否相同
     * 参数:
     * 1:异常类声明
     * 2:测试代码Lambda表达式
     */
    @Test
    void exceptionTesting() {
        Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
            try {
                System.out.println(1 / 0);
            }catch (Exception e){
                throw new IllegalArgumentException("非法的参数异常");
            }
        });
        assertEquals("非法的参数异常", exception.getMessage());
    }

    /**
     * assertTimeout()对方法执行时间进行测试
     * 实例中执行的代码部分必须在2分钟之内执行完毕,否则测试不通过
     */
    @Test
    void timeoutNotExceeded() {
        assertTimeout(Duration.ofMinutes(2), () -> {
            System.out.println(33+44);
        });
    }

    /**
     * assertTimeout()还可以接受一个返回值(泛型 T)
     * 被测试代码如果通过测试就返回一个值,这个值被assertTimeout()方法返回
     */
    @Test
    void timeoutNotExceededWithResult() {
        String actualResult = assertTimeout(Duration.ofMinutes(2), () -> {
            return "haha";
        });
        assertEquals("haha", actualResult);
    }

    /**
     * assertTimeout()毫秒案例
     */
    @Test
    void timeoutExceeded() {
        assertTimeout(Duration.ofMillis(10), () -> {
            Thread.sleep(100);
        });
    }
}

SpringBoot中使用Junit Junit4单元测试类写法:
@SpringBootTest
public class SpringDataES {
}
Junit5单元测试类写法:
@SpringBootTest
public class SpringDataES {
}

Junit5中RunWith注解已经被ExtendWith取代,而SpringBootTest注解,已经包含了ExtendWith: 在这里插入图片描述

关注
打赏
1665409997
查看更多评论
立即登录/注册

微信扫码登录

0.0469s