Junit 高级-ApiHug准备-测试篇-011

     🤗 ApiHug × {Postman|Swagger|Api...} = 快↑ 准√ 省↓

  1. GitHub - apihug/apihug.com: All abou the Apihug   
  2. apihug.com: 有爱,有温度,有质量,有信任
  3. ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace

涉及到 Junit5 一些深度不太常用的功能, 例子在:advancedopen in new window

#顺序

JUnit 5 支持下面几种 MethodOrderer:

  1. MethodName – 按照函数名字的字母排序。
  2. DisplayName – 按照显示名词的字母排序。
  3. OrderAnnotation – 按照 @Order annotation 排序,同order 排序方式可能不一致(所以尽量order 是散列的, 未标注的排最后面。
  4. Random – 随机排序 种子值可以通过系统配置: junit.jupiter.execution.order.random.seed 来配置。
  5. Custom – 定制扩展的排序类。

MethodNameOrderedTestsopen in new window 例子:

#MethodName

@TestMethodOrder(MethodOrderer.MethodName.class)
public class MethodNameOrderedTests 
{
    @Test
    void testE() {
        assertTrue(true);
    }
}

#DisplayName


@TestMethodOrder(MethodOrderer.DisplayName.class)
public class DisplayNameOrderedTests
{
    @DisplayName("5")
    @Test
    void testE() {
        assertTrue(true);
    }
}

#OrderAnnotation


@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class OrderAnnotationTests {
  @Order(5)
  @Test
  void testE() {
    assertTrue(true);
  }
}

#Random

修改 junit-platform.properties

junit.jupiter.execution.order.random.seed=9999

这个测试类, 每次执行的结果顺序都讲不一样!


@TestMethodOrder(MethodOrderer.Random.class)
public class RandomOrderedTests {
  @Test
  void testE() {
    assertTrue(true);
  }
}

#Custom

比如一个实现按照接口是否被 Deprecated, 排到最后进行测试:


public class DeprecatedInEndTestOrder implements MethodOrderer {

  private Comparator<MethodDescriptor> comparator =
      Comparator.comparing(md -> md.getMethod().isAnnotationPresent(Deprecated.class));

  @Override
  public void orderMethods(MethodOrdererContext context) {

    context.getMethodDescriptors().sort(comparator);
  }
}

然后参考测试用例:


@TestMethodOrder(DeprecatedInEndTestOrder.class)
public class CustomOrderTests {
  @Test
  @Deprecated
  void testC() {
    assertTrue(true);
  }

  @Test
  void testA() {
    assertTrue(true);
  }
}

当然也有正对,测试类自己的排序,这里不再赘述, 参考样例代码。

默认配置: junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$OrderAnnotation


@TestClassOrder(ClassOrderer.OrderAnnotation.class)
class OrderedTestClassesExample {

  @Nested
  @Order(1)
  class SetupTests {

    @Test
    void test1() {}
  }

  @Nested
  @Order(2)
  class AppFlowTests {

    @Test
    void test2() {}
  }
}

#Temp Dir

@TempDir 尚在实验功能open in new window 但是在一些场景下非常有用。

@TempDir 可以使用在方法参数, 类参数, 静态方法,可以用于构建 Fixture, 举个例子 测试目录open in new window


@Test
void tempDirectoryTestOne(@TempDir Path tempDir) throws IOException {
    Path tempFile = tempDir.resolve("test.txt");

    List<String> lines = Arrays.asList("dearxue.com");

    Files.write(tempFile, Arrays.asList("dearxue.com"));

    Assertions.assertTrue(Files.exists(tempFile), "Temp File should have been created");
    Assertions.assertEquals(Files.readAllLines(tempFile), lines);
}

@TempDir 作为成员变量, 那么每个测试用例都会创建一个新的临时测试目录, 然后再删除参考 TempDirTest2


test1 dir:  C:\Users\dearxue\AppData\Local\Temp\junit3449074755074304313
test2 dir:  C:\Users\dearxue\AppData\Local\Temp\junit7411092462858685015

@TempDir 作为静态成员变量, 和成员变量不一样, 这里一个测试类中不同测试方法会共享一个目录。

#测试名称

在一些场景下你希望获取测试名词, 可以通过 TestInfo 上下文获得 gettestname 例子open in new window


@Test
void givenNumbers_whenOddCheck_thenVerify(TestInfo testInfo) {
    System.out.println("displayName = " + testInfo.getDisplayName());
    int number = 5;
    assertTrue(oddCheck(number));
}

获得输出:

displayName = givenNumbers_whenOddCheck_thenVerify(TestInfo)

参数化场景可以通过 @BeforeEach 获得:

private TestInfo testInfo;

  @BeforeEach
  void init(TestInfo testInfo) {
    this.testInfo = testInfo;
  }

  private boolean oddCheck(int number) {
    return (number % 2 != 0);
  }

  @ParameterizedTest(name = "givenNumbers_whenOddCheck_thenVerify{0}")
  @ValueSource(ints = {1, 3, 5, -3, 15})
  void givenNumbers_whenOddCheck_thenVerify(int number) {
    System.out.println("displayName = " + testInfo.getDisplayName());
    assertTrue(oddCheck(number));
  }

输出为:


displayName = givenNumbers_whenOddCheck_thenVerify5
displayName = givenNumbers_whenOddCheck_thenVerify-3
displayName = givenNumbers_whenOddCheck_thenVerify3
displayName = givenNumbers_whenOddCheck_thenVerify1
displayName = givenNumbers_whenOddCheck_thenVerify15

#Test Instance

默认情况下, Junit 会为每个测试方法创建一个新的instance,这样保持状态的隔离:


class AdditionTest {

    private int sum = 1;

    @Test
    void addingTwoReturnsThree() {
        sum += 2;
        assertEquals(3, sum);
    }

    @Test
    void addingThreeReturnsFour() {
        sum += 3;
        assertEquals(4, sum);
    }
}

比如这个测试用例, 两个测试方法执行前, 新的事例被创建, sum 被初始化为1, 所以每个方法都能成立。

如果共享一个事例, 那么第二个方法会失败。

但是在一些情况下我们需要, 共享这些变量, 比如一些非常耗时的操作, 这个时候 TestInstance 派上用场了。

@TestInstance 两种模式一个是:LifeCycle.PER_METHOD (默认的), 另外一个是LifeCycle.PER_CLASS。

在 PER_CLASS 模式下, 我们可以看到下面例子的变量和方法都不是 static 但是能够照常运行。

@TestInstance(LifeCycle.PER_CLASS)
class TweetSerializerUnitTest {

    private String largeContent;

    @BeforeAll
    void setUpFixture() {
        // read the file
    }

#手动启动测试

你可以直接从 java 启动测试用例, 对整个junit 运行逐层debug,洞悉运行过程。

testRuntimeOnly("org.junit.platform:junit-platform-launcher") {
        because 'allows tests to run from IDEs that bundle older version of launcher'
}

添加依赖, 例子参考open in new window

public void runOne() {
    LauncherDiscoveryRequest request =
        LauncherDiscoveryRequestBuilder.request()
            .selectors(selectClass(FirstUnitTest.class))
            .build();
    Launcher launcher = LauncherFactory.create();
    TestPlan testPlan = launcher.discover(request);

    launcher.registerTestExecutionListeners(listener);
    launcher.execute(request);
  }

输出:


junit-5:RunJUnit5TestsFromJava.main()

Test run finished after 171 ms
[         6 containers found      ]
[         0 containers skipped    ]
[         6 containers started    ]
[         0 containers aborted    ]
[         6 containers successful ]
[         0 containers failed     ]
[        18 tests found           ]
[         0 tests skipped         ]
[        18 tests started         ]
[         0 tests aborted         ]
[        18 tests successful      ]
[         0 tests failed          ]

我们

api-hug-contact

  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于使用 JUnit Jupiter API 编写测试用例,可以按照以下步骤进行: 1. 导入依赖:首先,在你的项目中添加 JUnit Jupiter API 的依赖。如果你使用 Maven,则可以在 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.x.x</version> <scope>test</scope> </dependency> ``` 2. 创建测试类:在你的测试源代码目录中(通常是 `src/test/java`),创建一个新的测试类。这个类应该以 `Test` 结尾,并且包含一些测试方法。 ```java import org.junit.jupiter.api.Test; public class MyTestClass { @Test public void myTestMethod() { // 在这里编写你的测试逻辑 } } ``` 3. 编写测试方法:在测试类中,使用 `@Test` 注解来标记测试方法。测试方法应该是公共的、无返回值的,并且不带任何参数。 ```java @Test public void myTestMethod() { // 在这里编写你的测试逻辑 } ``` 4. 编写断言:在测试方法中,使用适当的断言来验证你的代码逻辑。JUnit Jupiter 提供了丰富的断言方法,例如 `assertEquals()`、`assertTrue()`、`assertNotNull()` 等等。 ```java @Test public void myTestMethod() { // 假设你正在测试一个计算器类的 add() 方法 Calculator calculator = new Calculator(); int result = calculator.add(2, 3); assertEquals(5, result); } ``` 5. 运行测试:使用你的构建工具(如 Maven 或 Gradle)运行测试。你也可以在 IDE 中直接运行测试方法。 这样,你就可以使用 JUnit Jupiter API 编写和运行测试用例了。希望这些步骤能帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值