1概要

このチュートリアルでは、EasyMock引数マッチャーを探ります。

さまざまな種類の定義済みマッチャーとカスタムマッチャーの作成方法についても説明します

EasyMockの基本についてはリンクですでに説明しています。


2単純なモッキングの例

さまざまなMatcherの探索を始める前に、コンテキストを見てみましょう。このチュートリアルでは、この例ではかなり基本的なユーザーサービスを使用します。

これが私たちのシンプルな

IUserService

インターフェースです。

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

そして関連する

User

モデル:

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

   //standard constructor, getters, setters
}

それで、私たちの

IUserService

をモックして、それを私たちの例で使うことから始めましょう:

private IUserService userService = mock(IUserService.class);

それでは、EasyMock引数マッチャーを調べてみましょう。


3平等マッチャー

まず、新しく追加された

User

と一致させるために

eq()

matcherを使用します。

@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);
}

このマッチャーはプリミティブとオブジェクトの両方で利用でき、

オブジェクトには

equals()

メソッドを使います

同様に、特定の

User

と一致させるために

same()

matcherを使用できます。

@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);
}


  • same()

    matcherは、 ”

    ==”

    ** を使用して引数を比較します。つまり、ここでは

    User

    インスタンスを比較します。

マッチャーを使用しない場合、引数はデフォルトで__equals()を使用して比較されます。

配列の場合は、

Arrays.equals()

メソッドに基づく

aryEq()

matcherもあります。


4任意の

Matcher


anyInt()



anyBoolean()



anyDouble()

、…​などのような任意のマッチャーがあります。** これらは引数が与えられた型を持つことを指定します。


anyString()を使用して、期待される

email

を任意の

String__値に一致させる例を見てみましょう。

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

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

引数を特定のクラスのインスタンスにするために、

isA()

を使用することもできます。

@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);
}

ここでは、

addUser()

メソッドパラメータが

User.

型であることを期待していると主張しています。


5ヌルマッチャー

次に、

isNull()

および

notNull()

マッチャーを使用して

null

値を一致させることができます。

次の例では、追加された

User

値がnullの場合に照合するために

isNull()

マッチャーを使用します。

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

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

追加されたユーザー値がnullでない場合にも、同じように

notNull()

を一致させることができます。

@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

引数と共に使用できる便利なマッチャーは複数あります。

まず、

startsWith()

マッチャーを使用して、ユーザーのメールアドレスのプレフィックスを照合します。

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

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

同様に、Eメールサフィックスに

endsWith()

マッチャーを使用します。

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

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

より一般的には、

contains()

を使用して電子メールを特定の部分文字列に一致させることができます。

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

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

あるいは、

matches()

を使用して特定の正規表現に電子メールを一致させることもできます。

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

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


7. ナンバーマッチャー

私達はまた私達が使用できる数値のための少数のmatcherを持っています。


lt()

マッチャーを使用してage引数を100未満にする例を見てみましょう。

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

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

同様に、age引数が10以上になるように

geq()

を使用します。

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

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

利用可能な番号マッチャーは以下のとおりです。


  • lt()

    – 与えられた値より小さい


  • leq()

    – より小さいか等しい


  • gt()

    – より大きい


  • geq()

    – 以上


8 Matcherを組み合わせる


と()



or()



not()

のマッチャーを使って複数のマッチャーを組み合わせることもできます。

年齢値が10を超え100未満であることを確認するために2つのマッチャーを組み合わせる方法を見てみましょう。

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

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

私たちが見ることができるもう一つの例は、“。com”で終わらない電子メールにマッチさせるために

not()



endsWith()

を組み合わせることです:

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

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


9カスタムマッチャー

最後に、カスタムEasyMockマッチャーを作成する方法について説明します。

目標は、指定された値以上の長さの文字列を照合するための単純な

minCharCount()

マッチャーを作成することです。

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

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

カスタム引数マッチャーを作成するには、次のことが必要です。


  • IArgumentMatcher

    インターフェースを実装する新しいクラスを作成する

  • 新しいマッチャー名で静的メソッドを作成して


reportMatcher()

を使用して上記のクラスのインスタンス

その中で無名クラスを宣言する

minCharCount()

メソッドの両方のステップを見てみましょう:

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;
}

また、

IArgumentMatcher

インターフェースには2つのメソッドがあります。


matches()

および

appendTo()。

最初のメソッドには引数の検証とマッチャーのロジックが含まれていますが、2番目のメソッドには失敗した場合にマッチャーの

String

表現を追加するために使用します。


10結論

EasyMockで定義されているさまざまなデータ型の引数マッチャーとカスタムマッチャーの作成方法について説明しました。

例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/testing-modules/mocks/mock-comparisons[GitHubで利用可能]です。