1. Overview
1.概述</span
JUnit becomes many developers’ first choice to perform unit tests on Java code. In real-world scenarios, one common testing requirement is to validate whether a given string conforms to a particular regular expression (regex) pattern.
JUnit 成为许多开发人员对 Java 代码执行单元测试的首选。在现实世界中,一种常见的测试要求是验证给定字符串是否符合特定的 正则表达式 (regex) 模式。
In this tutorial, we’ll explore several approaches to assert regex matches in JUnit, empowering us to test our string patterns effectively.
在本教程中,我们将探讨在 JUnit 中断言 regex 匹配的几种方法,使我们能够有效地测试我们的字符串模式。
2. Introduction to the Problem
2.问题介绍
The problem is quite simple: we want a natural and effective method to confirm that an input string aligns with a specific regex pattern. Ideally, we should also have a reliable approach to assert the opposite scenario, where an input string doesn’t match a regex pattern.
问题很简单:我们希望有一种自然而有效的方法来确认输入字符串是否与特定的 regex 模式一致。理想情况下,我们还应该有一种可靠的方法来断言相反的情况,即输入字符串与 regex 模式不匹配。
Let’s begin by exploring the widely-used JUnit 5 framework and learn how to perform assertions for regex pattern matches using its standard features. Additionally, we’ll discuss a potential pitfall when employing JUnit 5 for such assertions.
让我们从探索广泛使用的 JUnit 5 框架开始,学习如何使用其标准功能对 regex 模式匹配执行断言。此外,我们还将讨论在使用 JUnit 5 执行此类断言时可能存在的隐患。
Beyond JUnit 5, there are convenient and supplementary test and assertion libraries that seamlessly integrate with JUnit 5. In this tutorial, we’ll focus on two of these popular external libraries. We’ll look at how to assert regex pattern matches within the context of these libraries, expanding our toolkit for efficient testing.
除了 JUnit 5 之外,还有一些方便的辅助测试和断言库可与 JUnit 5 无缝集成。在本教程中,我们将重点介绍其中两个流行的外部库。我们将研究如何在这些库的上下文中断言 regex 模式匹配,从而扩展我们的工具包,实现高效测试。
3. Using the Standard JUnit 5 Methods
3.使用标准 JUnit 5 方法
JUnit 5 provides a series of frequently used assertions in the package org.junit.jupiter.api.Assertions, such as assertSame(), assertEquals(), and so on.
JUnit 5 在包 org.junit.jupiter.api.Assertions 中提供了一系列常用断言,例如 assertSame()、assertEquals()、 等。
Yet, JUnit 5 lacks dedicated assertion methods like “assertMatches()” for regex pattern validation. Since the String.matches() method returns a boolean, we can make use of the assertTrue() method to ensure a string matches a regex pattern:
然而,JUnit 5 中缺少像”assertMatches()“这样的专用断言方法来进行 regex 模式验证。由于 String.matches() 方法返回一个 布尔值,我们可以使用 assertTrue() 方法来确保字符串与 regex 模式相匹配: String.matches() 方法返回一个 布尔值。
assertTrue("Java at Baeldung".matches(".* at Baeldung$"));
Unsurprisingly, if we want to assert a string doesn’t match a regex pattern, we can use the assertFalse() assertion:
不难理解,如果我们要断言字符串与 regex 模式不匹配,可以使用 assertFalse() 断言:
assertFalse("something else".matches(".* at Baeldung$"));
4. Why We Shouldn’t Use the assertLinesMatch() Method for Regex Matching Tests
4.为什么我们不应该在 Regex 匹配测试中使用 assertLinesMatch() 方法?
While we mentioned earlier that JUnit 5 lacks dedicated regex pattern assertion methods, some might disagree with this statement. JUnit 5 indeed provides the assertLinesMatch() method, which can verify regex pattern matches within lines of text, for example:
虽然我们在前面提到 JUnit 5 缺乏专门的 regex 模式断言方法,但有些人可能不同意这种说法。JUnit 5 确实提供了 assertLinesMatch() 方法,例如,它可以验证文本行内的 regex 模式匹配:
assertLinesMatch(List.of(".* at Baeldung$"), List.of("Kotlin at Baeldung"));
As the example above shows, since the method accepts two lists (the expected list and the actual list) of strings, we wrapped the regex pattern and the input string in lists, and the test passes.
如上例所示,由于该方法接受两个字符串列表(预期列表和实际列表),因此我们用列表封装了 regex 模式和输入字符串,测试就通过了。
However, it’s worth noting that it isn’t safe to test regex matches using the assertLinesMatch() method. An example can show it quickly:
不过,值得注意的是, 使用 assertLinesMatch() 方法测试 regex 匹配并不安全。一个示例可以快速说明这一点:
assertFalse(".* at Baeldung$".matches(".* at Baeldung$"));
assertLinesMatch(List.of(".* at Baeldung$"), List.of(".* at Baeldung$"));
In the example above, our input string and the regex pattern are the same: “.* at Baeldung$“. Obviously, the input doesn’t match the pattern since the input string ends with a ‘$‘ character instead of “Baeldung“. So, the assertFalse() assertion passes.
在上面的示例中,我们的输入字符串和 regex 模式相同:”.* at Baeldung$“。显然,输入与模式不匹配,因为输入字符串以”$“字符结尾,而不是”Baeldung“。因此,assertFalse()断言通过。
Then, we pass the same input and the regex pattern to the assertLinesMatch() method, and the assertion has passed! This is because assertLinesMatch() verifies each pair from the expected list and the actual list in three steps:
然后,我们将相同的输入和 regex 模式传递给 assertLinesMatch() 方法,断言就通过了!这是因为 assertLinesMatch() 分三步验证了预期列表和实际列表中的每一对:
- If the expected string equals the actual string continue with the next pair
- Otherwise, treat the expected string as a regex pattern and check actualString.matches(expectedString). If the result is true, continue with the next pair
- Otherwise, if the expected string is a fast-forward marker, apply fast-forward actual lines accordingly and start from the first step
We won’t dive into the usage of the assertLinesMatches() method. As the steps above show, the regex pattern test is performed in step 2. In our example, the actual string, which is the input, and the expected string, the regex pattern, are equal. Therefore, the step 1 passed. That’s to say, the assertion passed without applying the regex-match check at all.
我们将不深入探讨 assertLinesMatches() 方法的用法。如上述步骤所示,regex 模式测试在第 2 步中进行。在我们的示例中,实际字符串(即输入字符串)和预期字符串(即 regex 模式)相等。因此,步骤 1 通过了。也就是说,断言完全没有应用 regex 匹配检查就通过了。
So, the assertLinesMatch() method isn’t the proper assertion method for validating regex pattern matches.
因此,assertLinesMatch() 方法并不是验证 regex 模式匹配的正确断言方法。
5. Using AssertJ’s matches() Method
5.使用 AssertJ 的 matches() 方法
With the popular AssertJ library, we can write fluent assertions quickly. AssertJ provides the matches() method to test regex patterns:
利用流行的 AssertJ 库,我们可以快速编写流畅的断言。AssertJ提供了matches()方法来测试regex模式:
// assertThat() below is imported from org.assertj.core.api.Assertions
assertThat("Linux at Baeldung").matches(".* at Baeldung$");
As the name implies, the doesNotMatch() method allows us to perform the negative test scenario:
顾名思义,doesNotMatch() 方法允许我们执行否定测试:
assertThat("something unrelated").doesNotMatch(".* at Baeldung$");
6. Using Hamcrest’s matchesPattern() Method
6.使用 Hamcrest 的 matchesPattern() 方法
Similarly, Hamcrest is another widely used testing framework. Also, it offers the matchesPattern() method for regex matching tests:
同样,Hamcrest 是另一个广泛使用的测试框架。此外,它还为 regex 匹配测试提供了 matchesPattern() 方法:
// assertThat() below is imported from org.hamcrest.MatcherAssert
assertThat("Computer science at Baeldung", matchesPattern(".* at Baeldung$"));
To perform a negative regex matching test, we can use not() to negate the Matcher created by matchesPattern():
要执行否定 regex 匹配测试,我们可以使用 not() 来否定由 matchesPattern() 创建的 Matcher : not() 是由 matchesPattern() 创建的。
assertThat("something unrelated", not(matchesPattern(".* at Baeldung$")));
7. Conclusion
7.结论</b
In this article, we’ve explored different ways to assert regex pattern matches.
在本文中,我们探讨了断言 regex 模式匹配的不同方法。</span
Two commonly used libraries, AssertJ and Hamcrest, offer dedicated regex matching test methods. On the other hand, JUnit 5’s assertTrue() combined with the String.matches() method can also achieve the same goal if we prefer to minimize external dependencies.
两个常用库 AssertJ 和 Hamcrest 提供了专门的 regex 匹配测试方法。另一方面,如果我们希望尽量减少外部依赖性,JUnit 5 的 assertTrue() 与 String.matches() 方法相结合也可以实现相同的目标。
Additionally, we’ve discussed that we shouldn’t use JUnit 5’s assertLinesMatch() for regex pattern matching tests.
此外,我们已经讨论过不应该使用 JUnit 5 的 assertLinesMatch() 进行 regex 模式匹配测试。
As always, the complete source code for the examples is available over on GitHub.
一如既往,示例的完整源代码可在 GitHub 上获取。 .