IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> JUnit5依赖注入与测试接口 -> 正文阅读

[开发测试]JUnit5依赖注入与测试接口

依赖注入
以前的JUnit的类构造方法和测试方法都是不能有参数的,JUnit Jupiter有一个颠覆性的改进,就是允许它们有入参,这样就能做依赖注入。

如果你对pytest的fixture有了解的话,就知道这个技术是多么的强大。

ParameterResolver是一个接口类,类构造方法和测试方法在运行时,必须由被注册的ParameterResolver进行解析。JUnit Jupiter有三个自动注册的内置解析器:

TestInfoParameterResolver 参数类型为TestInfo
RepetitionInfoParameterResolver 参数类型为RepetitionInfo
TestReporterParameterResolver 参数类型为TestReporter
TestInfo

TestInfo包含the display name, the test class, the test method, and associated tags等信息。

示例:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;

@DisplayName(“TestInfo Demo”)
class TestInfoDemo {

TestInfoDemo(TestInfo testInfo) {
    assertEquals("TestInfo Demo", testInfo.getDisplayName());
}

@BeforeEach
void init(TestInfo testInfo) {
    String displayName = testInfo.getDisplayName();
    assertTrue(displayName.equals("TEST 1") || displayName.equals("test2()"));
}

@Test
@DisplayName("TEST 1")
@Tag("my-tag")
void test1(TestInfo testInfo) {
    assertEquals("TEST 1", testInfo.getDisplayName());
    assertTrue(testInfo.getTags().contains("my-tag"));
}

@Test
void test2() {
}

}
RepetitionInfo

主要是@RepeatedTest会用到,包含当前重复以及总重复次数等信息。

TestReporter

TestReporter能用来输出额外的信息。

示例:

class TestReporterDemo {

@Test
void reportSingleValue(TestReporter testReporter) {
    testReporter.publishEntry("a status message");
}

@Test
void reportKeyValuePair(TestReporter testReporter) {
    testReporter.publishEntry("a key", "a value");
}

@Test
void reportMultipleKeyValuePairs(TestReporter testReporter) {
    Map<String, String> values = new HashMap<>();
    values.put("user name", "dk38");
    values.put("award year", "1974");

    testReporter.publishEntry(values);
}

}
传自定义参数

除内置解析器,如果想传自定义参数,那么需要使用@ExtendWith注册扩展,比如:

@ExtendWith(RandomParametersExtension.class)
class MyRandomParametersTest {

@Test
void injectsInteger(@Random int i, @Random int j) {
    assertNotEquals(i, j);
}

@Test
void injectsDouble(@Random double d) {
    assertEquals(0.0, d, 1.0);
}

}
有点插件的意思,更常见的是MockitoExtension和SpringExtension 。

测试接口
JUnit Jupiter除测试类和测试方法,其实也有测试接口,比如:

@TestInstance(Lifecycle.PER_CLASS)
interface TestLifecycleLogger {

static final Logger logger = Logger.getLogger(TestLifecycleLogger.class.getName());

@BeforeAll
default void beforeAllTests() {
    logger.info("Before all tests");
}

@AfterAll
default void afterAllTests() {
    logger.info("After all tests");
}

@BeforeEach
default void beforeEachTest(TestInfo testInfo) {
    logger.info(() -> String.format("About to execute [%s]",
        testInfo.getDisplayName()));
}

@AfterEach
default void afterEachTest(TestInfo testInfo) {
    logger.info(() -> String.format("Finished executing [%s]",
        testInfo.getDisplayName()));
}

}
interface TestInterfaceDynamicTestsDemo {

@TestFactory
default Stream<DynamicTest> dynamicTestsForPalindromes() {
    return Stream.of("racecar", "radar", "mom", "dad")
        .map(text -> dynamicTest(text, () -> assertTrue(isPalindrome(text))));
}

}
@Test, @RepeatedTest, @ParameterizedTest, @TestFactory, @TestTemplate, @BeforeEach, and @AfterEach能作用到接口的default方法上。

default方法是接口已经实现好了的方法,接口的实现类不需要再编写实现代码,就能直接使用 。

如果测试类是@TestInstance(Lifecycle.PER_CLASS)注解,那么可以使用@BeforeAll and @AfterAll。

测试接口可以作为模版。如果测试接口有@ExtendWith and @Tag注解,那么它的实现类也会继承tags and extensions。比如:

@Tag(“timed”)
@ExtendWith(TimingExtension.class)
interface TimeExecutionLogger {
}
class TestInterfaceDemo implements TestLifecycleLogger,
TimeExecutionLogger, TestInterfaceDynamicTestsDemo {

@Test
void isEqualValue() {
    assertEquals(1, "a".length(), "is always equal");
}

}
结果:

INFO example.TestLifecycleLogger - Before all tests
INFO example.TestLifecycleLogger - About to execute [dynamicTestsForPalindromes()]
INFO example.TimingExtension - Method [dynamicTestsForPalindromes] took 19 ms.
INFO example.TestLifecycleLogger - Finished executing [dynamicTestsForPalindromes()]
INFO example.TestLifecycleLogger - About to execute [isEqualValue()]
INFO example.TimingExtension - Method [isEqualValue] took 1 ms.
INFO example.TestLifecycleLogger - Finished executing [isEqualValue()]
INFO example.TestLifecycleLogger - After all tests
测试接口也可以作为契约。比如:

public interface Testable {

T createValue();

}
public interface EqualsContract extends Testable {

T createNotEqualValue();

@Test
default void valueEqualsItself() {
    T value = createValue();
    assertEquals(value, value);
}

@Test
default void valueDoesNotEqualNull() {
    T value = createValue();
    assertFalse(value.equals(null));
}

@Test
default void valueDoesNotEqualDifferentValue() {
    T value = createValue();
    T differentValue = createNotEqualValue();
    assertNotEquals(value, differentValue);
    assertNotEquals(differentValue, value);
}

}
public interface ComparableContract<T extends Comparable> extends Testable {

T createSmallerValue();

@Test
default void returnsZeroWhenComparedToItself() {
    T value = createValue();
    assertEquals(0, value.compareTo(value));
}

@Test
default void returnsPositiveNumberWhenComparedToSmallerValue() {
    T value = createValue();
    T smallerValue = createSmallerValue();
    assertTrue(value.compareTo(smallerValue) > 0);
}

@Test
default void returnsNegativeNumberWhenComparedToLargerValue() {
    T value = createValue();
    T smallerValue = createSmallerValue();
    assertTrue(smallerValue.compareTo(value) < 0);
}

}
实现类:

class StringTests implements ComparableContract, EqualsContract {

@Override
public String createValue() {
    return "banana";
}

@Override
public String createSmallerValue() {
    return "apple"; // 'a' < 'b' in "banana"
}

@Override
public String createNotEqualValue() {
    return "cherry";
}

}
小结
本文先介绍了JUnit Jupiter的颠覆性技术,允许传参以实现依赖注入,然后介绍了除了测试类和测试方法以外的测试接口,它既可以作为测试模板,也可以作为测试契约 。

参考资料:

https://junit.org/junit5/docs/current/user-guide/#writing-tests-dependency-injection

https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-interfaces-and-default-methods

https://blog.csdn.net/qq_35387940/article/details/104767746

IT之家

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 23:05:08  更:2021-07-22 23:05:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 6:24:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码