Edited at

【JMockit1.30】 Expectationsでの引数マッチングをさらに詳しく

More than 1 year has passed since last update.

JMockitのExpectationsの引数マッチングについて、詳しく調べると結構いろんなことができるよっていう紹介です。


前提条件

基本的な機能には触れません。

以下の記事がすごく分かりやすいです。

JMockit使い方メモ

上記に載ってないこと・変更されたことがメインです。


環境

JMockit1.30


NonStrictExpectationsについて

ver1.25 で削除されています。

ExpectationsでminTimes = 0を指定することでNonStrictExpectationsの代わりを行うことが出来ます。


引数のマッチング


Logic.java

/**

* テスト対象のクラス.
*/

public class Logic {

// DI
private Hoge hoge;

// テスト対象のメソッド
public void main() {

UserModel user = new UserModel("A123", "田中", 30);

String str = hoge.method(user);

...
}
}



Hoge.java

/**

* DIされるクラス.
*/

public class Hoge {

public String method(UserModel user) {
return "abc";
}

}



UserModel.java

/**

* User情報.
*/

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserModel {

/**
* ユーザID.
*/

private String id;

/**
* 名前.
*/

private String name;

/**
* 年齢.
*/

private int age;

}


上記でLogic.main()を実行した際のhoge.method(UserModel)の引数について検証を行う。


基本のマッチング


LogicTest.java

public class LogicTest {

@Tested
private Logic target;

@Injectable
private Hoge hoge;

@Test
public void 基本のマッチング() {

// Setup
UserModel assume = new UserModel() {
{
setId("A123");
setName("田中");
setAge(30);
}
};

new Expectations() {
{
// Verify
hoge.method(assume);
times = 1;
}
};

// Exercise
target.main();

}



  • 実行メソッドの引数に想定するオブジェクトのインスタンスを置くことで、実行時のインスタンスと想定するオブジェクトのインスタンスをObject.equalsで比較を行うことができる。

  • lombokの@Dataを利用した場合、Object.equalsは各プロパティ値の比較となる。

  • 上記の例はhoge.method(UserModel)の実行時の引数のユーザ情報がid = A123, name = 田中, 年齢 = 30であることを確認している。


Matcherでのマッチング


LogicTest.java

public class LogicTest {

@Tested
private Logic target;

@Injectable
private Hoge hoge;

@Test
public void Matcherでのマッチング() {

new Expectations() {
{
// Verify
hoge.method(withArgThat(
allOf(hasProperty("id", is("A123")), hasProperty("name", is("田中")))));
times = 1;
}
};

// Exercise
target.main();

}




  • withArgThat(Matcher)を用いることで、Hamcrest の Matcher を使って引数をマッチングすることができる。

  • 上記の例はhoge.method(UserModel)の実行時の引数のユーザ情報がid = A123, name = 田中であることを確認している。


Delegateでのマッチング


LogicTest.java

public class LogicTest {

@Tested
private Logic target;

@Injectable
private Hoge hoge;

@Test
public void Delegateでのマッチング() {

new Expectations() {
{
// Verify
hoge.method(with(new Delegate<UserModel>() {
boolean delegage(UserModel user) {
return user.getAge() >= 20;
}
}));
times = 1;
}
};

// Exercise
target.main();

}




  • with(Delegate)を用いることで、メソッドでアサーションを行うことが出来る。

  • Delegateの使い方はメソッド動作指定の場合とほとんど同じ。JMockit使い方メモの[Delegate を使ってモック化したメソッドの動作を指定する]を参照。

  • 戻り値の型をbooleanにしてアサーションを行う。

  • 上記の例はhoge.method(UserModel)の実行時の引数のユーザ情報の年齢が20以上であることを確認している。


withCaptureでのマッチング

別の例で説明します。HogeUserModelについては前回と同じ。


Logic.java

/**

* テスト対象のクラス.
*/

public class Logic {

@Inject
private Hoge hoge;

public void main2() {

List<UserModel> users = Arrays.asList(
new UserModel("A123", "田中", 30),
new UserModel("A124", "佐藤", 18),
new UserModel("A125", "鈴木", 25));

users.stream()
.map(hoge::method)
.forEach(System.out::println);
}

}



LogicTest.java

public class LogicTest {

@Tested
private Logic target;

@Injectable
private Hoge hoge;

@Test
public void Captureでのマッチング() {

// SetUp
List<UserModel> captures = new ArrayList<>();

new Expectations() {
{
hoge.method(withCapture(captures));
times = 3;
}
};

// Exercise
target.main2();

// Verify
assertThat(captures, hasSize(3));
assertThat(captures,
hasItem(allOf(hasProperty("id", is("A125")), hasProperty("name", is("鈴木")))));

}




  • withCapture(List)を用いることで、引数を指定したリストに取得することができる。

  • Listの実装はArrayListなどmutableなリストを使うこと。

  • 上記の例はhoge.method(UserModel)が三回実行され、その中でid = A125かつname = 鈴木のユーザが存在することを確認している。


参考

JMockit使い方メモ