3

ArgumentMatchers.matches( String regex ) exists... and it is possible to devise regexes which don't match a given String. But it is far from trivial (several threads in SO).

Is it wrong of me (or wrong-headed) to think it might be a nice idea to request the Mockito designers to take the heavy-lifting out of this and add it as a feature? It just seems that, in the context of mocking and so forth, it is a far-from-exceptional use case...

PS also, I'm not clear with ArgumentMatchers.matches how you go about saying "this may be a multiline String we're matching against, don't worry about it"... wouldn't it be better to have a Pattern rather than a simple String?

later

Feature request "enhanced" at Mockito HQ (on Github). "bric3" there says one should use Jeff Bowman's technique for "does not match". But she/he seems to think the Pattern idea is worth thinking about.

Re not(): Mockito's own documentation says "Use additional matchers very judiciously because they may impact readability of a test. It is recommended to use matchers from Matchers and keep stubbing and verification simple."

Also I find I must "possible dupe" my own question: How to write a matcher that is not equal to something. Searching with hindsight is always easier...!

later still

Many thanks to Brice for adding this so quickly. Updated my gradle.build and... new 4.1 core downloaded from Maven Central and immediately available for use.

Community
  • 1
  • 1
mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • 1
    This would be an excellent post for the Mockito mailing list. And you can always make a feature request to the Mockito team. Feature requests usually spark some debate within the team about whether or not the feature is a good idea - sometimes requested features get developed quickly, sometimes they take a while but get developed eventually, and sometimes they get rejected. But there's never any harm in making a request. – Dawood ibn Kareem Dec 21 '16 at 20:25
  • Thanks for the encouragement. Jeff Bowman's response goes in a totally different direction. AdditionalMatchers.not. I think it would propably have taken me about 13 years to have stumbled on that. There's probably only a small bunch of potential purchasers, but have any of you experts ever thought of writing a book entitled "Intermediate Mockito" or "Mockito: taking it to another level"? – mike rodent Dec 21 '16 at 21:01
  • Actually, I started work on a fairly comprehensive book on Mockito a few years ago. The problem is that Mockito is growing and changing faster than I can write, with new features being added all the time. By the time I get to publish, the information in my book would be out of date. So I have abandoned the project. What I really need to do is to start a blog and turn my material into a series of posts - maybe another day I'll do that. – Dawood ibn Kareem Dec 21 '16 at 21:04
  • Google Tomek Kaczanowski - he's written some good books on Mockito. – Dawood ibn Kareem Dec 21 '16 at 21:06
  • Of course. When I say "book" I don't envisage bits of paper. Might it be reasonable to suppose the pace of change is likely to slacken sooner or later? One of the things I have read over recent months while trying to teach myself mocking suggested that PowerMock, for example, possibly involves "too much magic". There's probably a natural plateau which Mockito will reach ... so it wouldn't be wasted effort on your part (necessarily!). – mike rodent Dec 21 '16 at 21:08
  • "Tomek Kaczanowski" - yep, one of the books I've spent many hours concentrating on. But it's not intermediate. There is no intermediate tutorial anywhere (that I'm aware of). – mike rodent Dec 21 '16 at 21:10
  • I'm not sure whether "not intermediate" means it's too basic or too advanced. – Dawood ibn Kareem Dec 21 '16 at 21:11
  • Yes, too basic (after a lot of head-scratching and experimenting... )... but I'm being told to stop! – mike rodent Dec 21 '16 at 21:13

2 Answers2

6

No need for a request: You can compose what you want using AdditionalMatchers.not.

when(yourComponent.acceptString(not(matches("foo|ba[rz]"))))
    .thenThrow(new IllegalArgumentException());

If you want to match a Pattern, you might need to write your own ArgumentMatcher subclass, but it's quite easy from there:

public class MatchesPattern implements ArgumentMatcher<String> {
  private final Pattern pattern;
  public MatchesPattern(Pattern pattern) { this.pattern = pattern; }

  @Override public boolean matches(String string) {
    return pattern.matcher(string).matches();
  }

  @Override public String toString() {
    return "[string matching /" + pattern.toString() + "/]";
  }

  /** Optional. */
  public static MatchesPattern matchesPattern(Pattern pattern) {
    return new MatchesPattern(pattern);
  }
}

You can then consume that class using:

when(yourComponent.acceptString(not(argThat(new MatchesPattern(yourPattern)))
    .thenThrow(new IllegalArgumentException());

// or with the static factory method:
when(yourComponent.acceptString(not(argThat(matchesPattern(yourPattern)))
    .thenThrow(new IllegalArgumentException());
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
4

For future readers, Mockito 2.4.1 has been released with support of the Pattern class :

Now you should be abble to write :

when(yourComponent.acceptString(not(matches(Pattern.compile(...)))
    .thenThrow(new IllegalArgumentException());
bric3
  • 40,072
  • 9
  • 91
  • 111