Repository: mockito/mockito
Issue: Feature request: ArgumentMatchers.matches(Pattern regex)
Labels: enhancement

you ladies and gentlemen are geniuses by the way.

ArgumentMatchers.match( String regex ) exists... but wouldn't it be slightly better if it were match( Pattern regex )? (i.e. catering for multi-line Strings, etc.).

Also, devising a regex which distinctly does NOT match a given String is non-trivial.  And yet not atypical of a mocking use case.  Hence I suggest you clever people take the heavy lifting away from grunts like me by offering ArgumentMatchers.doesNotMatch( Pattern regex ).

I posed this question today on Stack Overflow [here](http://stackoverflow.com/questions/41270738/mockito-argumentmatchers-doesnotmatch?noredirect=1#comment69745269_41270738).  

------

**EDIT 1** by @bric3 : removed the issue guidelines
**EDIT 2** by @bric3 : Renamed the issue title. Previous title was `Feature request: ArgumentMatchers.doesNotMatch( Pattern regex )`

Issue comments:
As the question is answered in SO, you can negate matchers using `AdditionalMatchers.not()`.

I think I can close this issue.
OK... but this question highlights the fact that the online documentation and tutorials are not optional, they are essential ... and they are currently inadequate.  People who are willing to learn shouldn't have to pose a question for such an obvious use case on SO.
Hi,

I closed the issue because it is about a feature request that is not valid since the feature is already present in a different form. Now documentation and tutorial is another thing.

`AdditionalMatchers` is mentionned on the first line of the [ArgumentMatchers javadoc](https://static.javadoc.io/org.mockito/mockito-core/2.4.0/org/mockito/ArgumentMatchers.html). The Mockito javadoc gives plenty of code examples on the public API, which is already more than most javadoc in almost every project. 

I'm not saying it can't improved or we won't improve it, it can and we will! On the matter at hand those matchers can be promoted a bit more to enhance discoverability.

Regarding tutorials I believe it is the responsibility of respective blog authors.

In the mean time pull requests are welcome, and the wiki can be edited by any benevolent soul.
Also it seems I skipped the part on the `Pattern` class, reopening for the `matches(Pattern)` matcher.


Oh... good.  No really!  The multi-line challenge has me foxed... indeed.  :)
The builds should propagate within an hour (note that badges or search.maven.org may not be up to date)
Hi Brice... thanks for doing this so quickly.  I have upgraded my gradle.build and got hold of your new build.  But I am still having problems using "not" with this... if you have a moment maybe you might look at my new edit at [SO](http://stackoverflow.com/questions/41270738/mockito-argumentmatchers-doesnotmatch).
It looks like an import issue, either for `not` or `matches`. I've tested it yesterday, when I added the API.
Yes, you're right: it's an AssertJ confusion: Eclipse imported NotFilter.not() automatically.  Apologies.

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/ArgumentMatchers.java b/src/main/java/org/mockito/ArgumentMatchers.java
index 66d05a7ac0..56ff53311f 100644
--- a/src/main/java/org/mockito/ArgumentMatchers.java
+++ b/src/main/java/org/mockito/ArgumentMatchers.java
@@ -4,8 +4,6 @@
  */
 package org.mockito;
 
-import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
-import static org.mockito.internal.util.Primitives.defaultValue;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -13,6 +11,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Pattern;
 import org.mockito.internal.matchers.Any;
 import org.mockito.internal.matchers.Contains;
 import org.mockito.internal.matchers.EndsWith;
@@ -26,6 +25,9 @@
 import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
 import org.mockito.internal.util.Primitives;
 
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+import static org.mockito.internal.util.Primitives.defaultValue;
+
 /**
  * Allow flexible verification or stubbing. See also {@link AdditionalMatchers}.
  *
@@ -93,6 +95,12 @@
  * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.
  * </p>
  *
+ * <h1>Additional matchers</h1>
+ * <p>
+ * The class {@link AdditionalMatchers} offers rarely used matchers, although they can be useful, when
+ * it is useful to combine multiple matchers or when it is useful to negate a matcher necessary.
+ * </p>
+ *
  * <h1>Custom Argument ArgumentMatchers</h1>
  * <p>
  * It is important to understand the use cases and available options for dealing with non-trivial arguments
@@ -1104,12 +1112,29 @@ public static String contains(String substring) {
      *
      * @param regex the regular expression.
      * @return empty String ("").
+     *
+     * @see AdditionalMatchers#not(boolean)
      */
     public static String matches(String regex) {
         reportMatcher(new Matches(regex));
         return "";
     }
 
+    /**
+     * <code>Pattern</code> argument that matches the given regular expression.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param pattern the regular expression pattern.
+     * @return empty String ("").
+     *
+     * @see AdditionalMatchers#not(boolean)
+     */
+    public static String matches(Pattern pattern) {
+        reportMatcher(new Matches(pattern));
+        return "";
+    }
+
     /**
      * <code>String</code> argument that ends with the given suffix.
      * <p>
diff --git a/src/main/java/org/mockito/internal/matchers/Matches.java b/src/main/java/org/mockito/internal/matchers/Matches.java
index 6ebb4a8368..2a15c47480 100644
--- a/src/main/java/org/mockito/internal/matchers/Matches.java
+++ b/src/main/java/org/mockito/internal/matchers/Matches.java
@@ -5,23 +5,27 @@
 
 package org.mockito.internal.matchers;
 
-import org.mockito.ArgumentMatcher;
-
 import java.io.Serializable;
+import java.util.regex.Pattern;
+import org.mockito.ArgumentMatcher;
 
 public class Matches implements ArgumentMatcher<Object>, Serializable {
 
-    private final String regex;
+    private final Pattern pattern;
 
     public Matches(String regex) {
-        this.regex = regex;
+        this(Pattern.compile(regex));
+    }
+
+    public Matches(Pattern pattern) {
+        this.pattern = pattern;
     }
 
     public boolean matches(Object actual) {
-        return (actual instanceof String) && ((String) actual).matches(regex);
+        return (actual instanceof String) && pattern.matcher((String) actual).matches();
     }
 
     public String toString() {
-        return "matches(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")";
+        return "matches(\"" + pattern.pattern().replaceAll("\\\\", "\\\\\\\\") + "\")";
     }
-}
\ No newline at end of file
+}


Test patch:
diff --git a/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java b/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java
index c62756bcd4..9611dee2a6 100644
--- a/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java
+++ b/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java
@@ -5,6 +5,7 @@
 
 package org.mockito.internal.matchers;
 
+import java.util.regex.Pattern;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;
 import org.mockitoutil.TestBase;
@@ -113,6 +114,7 @@ public void findToString() {
     @Test
     public void matchesToString() {
         assertEquals("matches(\"\\\\s+\")", new Matches("\\s+").toString());
+        assertEquals("matches(\"\\\\s+\")", new Matches(Pattern.compile("\\s+")).toString());
     }
 
 }
diff --git a/src/test/java/org/mockitousage/matchers/MatchersTest.java b/src/test/java/org/mockitousage/matchers/MatchersTest.java
index 762d0ee3e5..f151a84396 100644
--- a/src/test/java/org/mockitousage/matchers/MatchersTest.java
+++ b/src/test/java/org/mockitousage/matchers/MatchersTest.java
@@ -5,6 +5,22 @@
 
 package org.mockitousage.matchers;
 
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.RandomAccess;
+import java.util.regex.Pattern;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotSame;
+import static junit.framework.TestCase.fail;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.AdditionalMatchers.and;
 import static org.mockito.AdditionalMatchers.aryEq;
@@ -43,20 +59,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotSame;
-import static junit.framework.TestCase.fail;
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.RandomAccess;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.mockito.exceptions.verification.WantedButNotInvoked;
-import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
-import org.mockitousage.IMethods;
-import org.mockitoutil.TestBase;
 
 
 @SuppressWarnings("unchecked")
@@ -499,6 +501,16 @@ public void matches_matcher() {
         assertEquals(null, mock.oneArg("blah"));
     }
 
+    @Test
+    public void matches_Pattern_matcher() {
+        when(mock.oneArg(matches(Pattern.compile("[a-z]+\\d\\d")))).thenReturn("1");
+        when(mock.oneArg(matches(Pattern.compile("\\d\\d\\d")))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg("a12"));
+        assertEquals("2", mock.oneArg("131"));
+        assertEquals(null, mock.oneArg("blah"));
+    }
+
     @Test
     public void contains_matcher() {
         when(mock.oneArg(contains("ell"))).thenReturn("1");
@@ -600,4 +612,4 @@ public void nullable_matcher() throws Exception {
 
         verify(mock, times(2)).oneArg(nullable(Character.class));
     }
-}
\ No newline at end of file
+}