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でのマッチング
別の例で説明します。Hoge
とUserModel
については前回と同じ。
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 = 鈴木のユーザが存在することを確認している。