【问题标题】:Assert regex matches in JUnit在 JUnit 中断言正则表达式匹配
【发布时间】:2012-01-20 06:24:48
【问题描述】:

Ruby 的 Test::Unit 有一个很好的 assert_matches 方法,可以在单元测试中使用它来断言正则表达式匹配字符串。

在 JUnit 中有这样的东西吗?目前,我这样做:

assertEquals(true, actual.matches(expectedRegex));

【问题讨论】:

    标签: java regex junit


    【解决方案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 方法。

      【讨论】:

      【解决方案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 无法像 assertEqualsassertThat 那样为您提供详细信息
            • @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);
              

              【讨论】:

                猜你喜欢
                • 2020-04-15
                • 1970-01-01
                • 1970-01-01
                • 2014-05-14
                • 2019-09-12
                • 2014-01-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多