在 JUnit 中断言正则表达式匹配
Posted
技术标签:
【中文标题】在 JUnit 中断言正则表达式匹配【英文标题】:Assert regex matches in JUnit 【发布时间】:2012-01-20 06:24:48 【问题描述】:Ruby 的 Test::Unit
有一个很好的 assert_matches
方法,可以在单元测试中使用它来断言正则表达式匹配字符串。
在 JUnit 中有这样的东西吗?目前,我这样做:
assertEquals(true, actual.matches(expectedRegex));
【问题讨论】:
【参考方案1】:JUnit 5 的更新,没有任何额外的库。
现在您可以按照https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/Assertions.html#assertLinesMatch-java.util.List-java.util.List- 中的说明使用assertLinesMatch
创建断言是为了匹配多行文本,因此即使您尝试仅匹配一行,您也需要提供List
。例如:
assertLinesMatch(List.of("Expected at the beginning.*"), List.of(contentUnderTest));
断言算法将尝试精确匹配,然后,如果失败,将使用String.match
将预期值解释为正则表达式。
重要提示:如果您的 contentUnderTest
包含多行,则正则表达式中的 .*
将不起作用(.
不匹配默认为换行符),因此您可能需要添加嵌入标志(https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#DOTALL):
// Flag ?s means match new lines
assertLinesMatch(List.of("(?s)Expected at the beginning.*"), List.of(contentWithMultipleLines));
【讨论】:
【参考方案2】:如果您使用assertThat()
和Hamcrest matcher 来测试正则表达式匹配,那么如果断言失败,您将收到一条很好的消息,指示预期的模式和实际文本。断言也会更流畅地阅读,例如
assertThat("FooBarBaz", matchesPattern("^Foo"));
使用 Hamcrest 2,您可以在 MatchesPattern.matchesPattern
找到 matchesPattern
方法。
【讨论】:
Hamcrest 2.0 现在内置了Matchers.matchesPattern(String)
:github.com/hamcrest/JavaHamcrest/blob/master/hamcrest-library/…
@hinneLinks 所指内容的固定链接:github.com/hamcrest/JavaHamcrest/blob/…【参考方案3】:
Hamcrest中有对应的matcher:org.hamcrest.Matchers.matchesPattern(String regex)。
As development of Hamcrest stalled你不能使用最新的可用 v1.3:
testCompile("org.hamcrest:hamcrest-library:1.3")
相反,您需要使用新的开发系列(但仍然是dated by Jan 2015):
testCompile("org.hamcrest:java-hamcrest:2.0.0.0")
甚至更好:
configurations
testCompile.exclude group: "org.hamcrest", module: "hamcrest-core"
testCompile.exclude group: "org.hamcrest", module: "hamcrest-library"
dependencies
testCompile("org.hamcrest:hamcrest-junit:2.0.0.0")
测试中:
Assert.assertThat("123456", Matchers.matchesPattern("^[0-9]+$"));
【讨论】:
我收到错误:在模块 jetified-hamcrest-core-1.3.jar (org.hamcrest:hamcrest-core:1.3) 和 jetified-java-hamcrest-2.0 中发现重复的类 org.hamcrest.BaseDescription .0.0.jar (org.hamcrest:java-hamcrest:2.0.0.0)【参考方案4】:使用 assertj 的另一种选择。这种方法很好,因为它允许您直接传递模式对象。
import static org.assertj.core.api.Assertions.assertThat;
assertThat("my\nmultiline\nstring").matches(Pattern.compile("(?s)my.*string", Pattern.MULTILINE));
【讨论】:
【参考方案5】:你可以使用 Hamcrest 和 jcabi-matchers:
import static com.jcabi.matchers.RegexMatchers.matchesPattern;
import static org.junit.Assert.assertThat;
assertThat("test", matchesPattern("[a-z]+"));
更多详情在这里:Regular Expression Hamcrest Matchers。
您将需要在类路径中使用这两个依赖项:
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-matchers</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
【讨论】:
我发现不需要hamcrest-core依赖【参考方案6】:与 Ralph 的实现类似的匹配器已被 added 提供给官方 Java Hamcrest 匹配器库。不幸的是,它还没有在发布包中可用。课程在GitHub,不过如果你想看看的话。
【讨论】:
【参考方案7】:您可以使用 Hamcrest,但您必须编写自己的匹配器:
public class RegexMatcher extends TypeSafeMatcher<String>
private final String regex;
public RegexMatcher(final String regex)
this.regex = regex;
@Override
public void describeTo(final Description description)
description.appendText("matches regex=`" + regex + "`");
@Override
public boolean matchesSafely(final String string)
return string.matches(regex);
public static RegexMatcher matchesRegex(final String regex)
return new RegexMatcher(regex);
用法
import org.junit.Assert;
Assert.assertThat("test", RegexMatcher.matchesRegex(".*est");
【讨论】:
【参考方案8】:据我所知,没有其他选择。刚刚检查了assert javadoc 以确保。 不过,只是一点点变化:
assertTrue(actual.matches(expectedRegex));
编辑:自从 pholser 的回答以来,我一直在使用 Hamcrest 匹配器,也请检查一下!
【讨论】:
啊,是的,assertTrue()
肯定更好。我责怪 Eclipse 的自动完成功能,因为我对此一无所知。 ;)
当测试失败时,assertTrue
无法像 assertEquals
或 assertThat
那样为您提供详细信息
@Michael 当然可以。 assertTrue("Expected string matching '" +expectedRegex+ "'. Got: "+actual, actual.matches(expectedRegex));
。不过它不如 Hamcrest 好。
@MikeValenty 如果您只是将一个值与is(true)
进行比较,那么assertThat
不会提供比assertTrue
更多的细节。要获得正确的错误消息,您需要一个不同的匹配器(或者您按照@MikeFHay 的建议手动构建消息)。
重要提示:string.matches() 可从 Java 版本 8 开始使用,在该版本中它不支持多行,即使使用相应的标志 (?m);那么您需要以旧的详细方式进行操作:Pattern.compile() 然后 matcher.find()【参考方案9】:
因为我也在寻找这个功能,所以我在 GitHub 上启动了一个名为 regex-tester 的项目。它是一个有助于在 Java 中轻松测试正则表达式的库(目前仅适用于 JUnit)。
这个库现在非常有限,但它确实有一个像这样工作的 Hamcrest 匹配器
assertThat("test", doesMatchRegex("tes.+"));
assertThat("test", doesNotMatchRegex("tex.+"));
更多关于如何使用 regex-tester 的信息是here。
【讨论】:
【参考方案10】:它不是 JUnit,但这是 fest-assert 的另一种方式:
assertThat(myTestedValue).as("your value is so so bad").matches(expectedRegex);
【讨论】:
以上是关于在 JUnit 中断言正则表达式匹配的主要内容,如果未能解决你的问题,请参考以下文章