EasyMock-Argumentvergleicher

EasyMock-Argumentvergleiche

1. Überblick

In diesem Tutorial werden EasyMock-Argument-Matcher untersucht. We’ll discuss different types of predefined matchers and how to create a custom matcher ebenfalls.

Wir haben die EasyMock-Grundlagen bereits im Artikel vonintroduction to EasyMockbehandelt. Daher müssen Sie sie möglicherweise zuerst lesen, um sich mit EasyMock vertraut zu machen.

2. Einfaches Verspottungsbeispiel

Bevor wir verschiedene Matcher untersuchen, werfen wir einen Blick auf unseren Kontext. In diesem Tutorial verwenden wir in unseren Beispielen einen ziemlich einfachen Benutzerdienst.

Hier ist unsere einfacheIUserService-Schnittstelle:

public interface IUserService {
    public boolean addUser(User user);
    public List findByEmail(String email);
    public List findByAge(double age);
}

Und das verwandte Modell vonUser:

public class User {
    private long id;
    private String firstName;
    private String lastName;
    private double age;
    private String email;

    // standard constructor, getters, setters
}

Wir beginnen also damit, nur unsereIUserServicezu verspotten, um sie in unseren Beispielen zu verwenden:

private IUserService userService = mock(IUserService.class);

Lassen Sie uns nun die EasyMock-Argument-Matcher untersuchen.

3. Gleichstellungs-Matcher

Zuerst verwenden wir den Matcher voneq(), um den neu hinzugefügtenUser zu entsprechen:

@Test
public void givenUserService_whenAddNewUser_thenOK() {
    expect(userService.addUser(eq(new User()))).andReturn(true);
    replay(userService);

    boolean result = userService.addUser(new User());
    verify(userService);
    assertTrue(result);
}

Dieser Matcher ist sowohl für Grundelemente als auch für Objekte unduses the equals() method for objects verfügbar.

In ähnlicher Weise können wirsame() Matcher zum Abgleichen eines bestimmtenUser verwenden:

@Test
public void givenUserService_whenAddSpecificUser_thenOK() {
    User user = new User();

    expect(userService.addUser(same(user))).andReturn(true);
    replay(userService);

    boolean result = userService.addUser(user);
    verify(userService);
    assertTrue(result);
}

The same() matcher compares arguments using “==”, was bedeutet, dass in unserem FallUser Instanzen verglichen werden.

Wenn wir keine Matcher verwenden, werden Argumente standardmäßig mitequals(). verglichen

Für Arrays haben wir auch denaryEq() Matcher, der auf derArrays.equals() Methode basiert.

4. Any Matcher

Es gibt mehrere Matcher wieanyInt(),anyBoolean(),anyDouble() usw. These specify that the argument should have the given type.

Sehen wir uns ein Beispiel für die Verwendung vonanyString() an, um den erwartetenemail als beliebigen Wert fürStringzu entsprechen:

@Test
public void givenUserService_whenSearchForUserByEmail_thenFound() {
    expect(userService.findByEmail(anyString()))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

Wir können auchisA() verwenden, um ein Argument als Instanz einer bestimmten Klasse abzugleichen:

@Test
public void givenUserService_whenAddUser_thenOK() {
    expect(userService.addUser(isA(User.class))).andReturn(true);
    replay(userService);

    boolean result = userService.addUser(new User());
    verify(userService);
    assertTrue(result);
}

Hier behaupten wir, dass wir erwarten, dass der MethodenparameteraddUser()vom TypUser. ist

5. Null-Matcher

Als nächsteswe can use the isNull() and notNull() matchers to match null values.

Im folgenden Beispiel verwenden wir den MatcherisNull(), um eine Übereinstimmung zu erzielen, wenn der hinzugefügte Wert vonUsernull ist:

@Test
public void givenUserService_whenAddNull_thenFail() {
    expect(userService.addUser(isNull())).andReturn(false);
    replay(userService);

    boolean result = userService.addUser(null);
    verify(userService);
    assertFalse(result);
}

Wir können auchnotNull() übereinstimmen, wenn der hinzugefügte Benutzerwert auf ähnliche Weise nicht null ist:

@Test
public void givenUserService_whenAddNotNull_thenOK() {
    expect(userService.addUser(notNull())).andReturn(true);
    replay(userService);

    boolean result = userService.addUser(new User());
    verify(userService);
    assertTrue(result);
}

6. String Matcher

Es gibt mehrere nützliche Matcher, die wir mit den Argumenten vonStringverwenden können.

Zunächst verwenden wir den MatcherstartsWith(), um das E-Mail-Präfix eines Benutzers abzugleichen:

@Test
public void whenSearchForUserByEmailStartsWith_thenFound() {
    expect(userService.findByEmail(startsWith("test")))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

In ähnlicher Weise verwenden wir den MatcherendsWith()für das E-Mail-Suffix:

@Test
public void givenUserService_whenSearchForUserByEmailEndsWith_thenFound() {
    expect(userService.findByEmail(endsWith(".com")))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

Im Allgemeinen können wircontains() verwenden, um die E-Mail mit einem bestimmten Teilstring abzugleichen:

@Test
public void givenUserService_whenSearchForUserByEmailContains_thenFound() {
    expect(userService.findByEmail(contains("@")))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

Oder ordnen Sie unsere E-Mail mitmatches() einem bestimmten regulären Ausdruck zu:

@Test
public void givenUserService_whenSearchForUserByEmailMatches_thenFound() {
    expect(userService.findByEmail(matches(".+\\@.+\\..+")))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

7. Number Matchers

Wir haben auch einige Matcher für numerische Werte, die wir verwenden können.

Sehen wir uns ein Beispiel für die Verwendung des Matcherslt()an, um das Altersargument auf weniger als 100 abzustimmen:

@Test
public void givenUserService_whenSearchForUserByAgeLessThan_thenFound() {
    expect(userService.findByAge(lt(100.0)))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByAge(20);
    verify(userService);
    assertEquals(0,result.size());
}

In ähnlicher Weise verwenden wir auchgeq(), um das Altersargument so anzupassen, dass es größer oder gleich 10 ist:

@Test
public void givenUserService_whenSearchForUserByAgeGreaterThan_thenFound() {
    expect(userService.findByAge(geq(10.0)))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByAge(20);
    verify(userService);
    assertEquals(0,result.size());
}

Die verfügbaren Nummernvergleicher sind:

  • lt() - kleiner als der angegebene Wert

  • leq() - kleiner oder gleich

  • gt() - größer als

  • geq() - größer oder gleich

8. Kombiniere Matcher

Wir können auch mehrere Matcher mitand(),or() undnot() Matchern kombinieren.

Mal sehen, wie wir zwei Matcher kombinieren können, um zu überprüfen, ob der Alterswert sowohl größer als 10 als auch kleiner als 100 ist:

@Test
public void givenUserService_whenSearchForUserByAgeRange_thenFound() {
    expect(userService.findByAge(and(gt(10.0),lt(100.0))))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByAge(20);
    verify(userService);
    assertEquals(0,result.size());
}

Ein weiteres Beispiel ist die Kombination vonnot() mitendsWith(), um E-Mails abzugleichen, die nicht mit ".com" enden:

@Test
public void givenUserService_whenSearchForUserByEmailNotEndsWith_thenFound() {
    expect(userService.findByEmail(not(endsWith(".com"))))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

9. Benutzerdefinierter Matcher

Abschließend wird erläutert, wie Sie einen benutzerdefinierten EasyMock-Matcher erstellen.

Das Ziel besteht darin, einen einfachenminCharCount()-Matcher zu erstellen, um Zeichenfolgen mit einer Länge größer oder gleich dem angegebenen Wert abzugleichen:

@Test
public void givenUserService_whenSearchForUserByEmailCharCount_thenFound() {
    expect(userService.findByEmail(minCharCount(5)))
      .andReturn(Collections.emptyList());
    replay(userService);

    List result = userService.findByEmail("[email protected]");
    verify(userService);
    assertEquals(0,result.size());
}

Um einen benutzerdefinierten Argumentvergleich zu erstellen, müssen wir:

  • Erstellen Sie eine neue Klasse, die dieIArgumentMatcher-Schnittstelle implementiert

  • Erstellen Sie eine statische Methode mit dem neuen Matchernamen und registrieren Sie eine Instanz der obigen Klasse mitreportMatcher()

Sehen wir uns beide Schritte in unsererminCharCount()-Methode an, die eine anonyme Klasse darin deklariert:

public static String minCharCount(int value){
    EasyMock.reportMatcher(new IArgumentMatcher() {
        @Override
        public boolean matches(Object argument) {
            return argument instanceof String
              && ((String) argument).length() >= value;
        }

        @Override
        public void appendTo(StringBuffer buffer) {
            buffer.append("charCount(\"" + value + "\")");
        }
    });
    return null;
}

Beachten Sie außerdem, dass die SchnittstelleIArgumentMatcherzwei Methoden hat:matches() undappendTo(). 

Die erste Methode enthält die Argumentvalidierung und Logik für unseren Matcher, während die zweite verwendet wird, um die Darstellung des MatchersStringanzuhängen, die im Fehlerfall gedruckt werden soll.

10. Fazit

Wir haben vordefinierte EasyMock-Argument-Matcher für verschiedene Datentypen und die Erstellung unserer benutzerdefinierten Matcher behandelt.

Der vollständige Quellcode für die Beispiele istover on GitHub verfügbar.