Assert regex matches in JUnit
JavaRegexJunitJava Problem Overview
Ruby's Test::Unit
has a nice assert_matches
method that can be used in unit tests to assert that a regex matches a string.
Is there anything like this in JUnit? Currently, I do this:
assertEquals(true, actual.matches(expectedRegex));
Java Solutions
Solution 1 - Java
If you use assertThat()
with a Hamcrest matcher that tests for regex matches, then if the assertion fails you'll get a nice message that indicates expected pattern and actual text. The assertion will read more fluently also, e.g.
assertThat("FooBarBaz", matchesPattern("^Foo"));
with Hamcrest 2 you can find a matchesPattern
method at MatchesPattern.matchesPattern
.
Solution 2 - Java
No other choice that I know. Just checked the assert javadoc to be sure. Just a tiny little change, though:
assertTrue(actual.matches(expectedRegex));
EDIT: I have been using the Hamcrest matchers since pholser's answer, check that out too!
Solution 3 - Java
You can use Hamcrest, but you have to write your own matcher:
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);
}
}
usage
import org.junit.Assert;
Assert.assertThat("test", RegexMatcher.matchesRegex(".*est");
Solution 4 - Java
You can use Hamcrest and jcabi-matchers:
import static com.jcabi.matchers.RegexMatchers.matchesPattern;
import static org.junit.Assert.assertThat;
assertThat("test", matchesPattern("[a-z]+"));
More details here: Regular Expression Hamcrest Matchers.
You will need these two dependencies in classpath:
<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>
Solution 5 - Java
Because I was also looking for this functionality, I have started a project on GitHub called regex-tester. It's a library that helps ease testing regular expressions in Java (only works with JUnit currently).
The library is very limited right now, but it does have a Hamcrest matcher that works like this
assertThat("test", doesMatchRegex("tes.+"));
assertThat("test", doesNotMatchRegex("tex.+"));
More about how to use regex-tester is here.
Solution 6 - Java
A matcher similar to Ralph's implementation has been added to the official Java Hamcrest matchers library. Unfortunately, it's not yet available in a release package. The class is on GitHub though if you want a look.
Solution 7 - Java
another alternative using assertj. this approach is nice as it allows you to pass the pattern object directly.
import static org.assertj.core.api.Assertions.assertThat;
assertThat("my\nmultiline\nstring").matches(Pattern.compile("(?s)my.*string", Pattern.MULTILINE));
Solution 8 - Java
There is corresponding matcher in Hamcrest: org.hamcrest.Matchers.matchesPattern(String regex).
As development of Hamcrest stalled you can't use latest available v1.3:
testCompile("org.hamcrest:hamcrest-library:1.3")
Instead you need to use new dev series (but still dated by Jan 2015):
testCompile("org.hamcrest:java-hamcrest:2.0.0.0")
or even better:
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")
}
In test:
Assert.assertThat("123456", Matchers.matchesPattern("^[0-9]+$"));
Solution 9 - Java
it's not JUnit but here is another way with fest-assert :
assertThat(myTestedValue).as("your value is so so bad").matches(expectedRegex);
Solution 10 - Java
An update for JUnit 5, without any extra library.
Now you can use assertLinesMatch
as described in https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/Assertions.html#assertLinesMatch-java.util.List-java.util.List-
The assertion was created to match several lines of text, so you need to provide a List
even if you try to match only one line. For e.g.:
assertLinesMatch(List.of("Expected at the beginning.*"), List.of(contentUnderTest));
The assertion algorithm will try an exact match and then, if it fails, will use String.match
interpreting the expected value as a regular expression.
An important note: if your contentUnderTest
contains several lines, then the .*
in the regex won't work (.
doesn't match a new line character by default) so you may need to add an embedded flag (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));