マッチャーおよびプリミティブ型での jmockit 期待値の使用
-
01-07-2019 - |
質問
私は単体テスト(TestNGによる)にjmockitを使用していますが、マッチャーを使用してプリミティブ型(ブール値)をパラメータとして受け取るメソッドを模擬するExpectationsクラスの使用に問題があります。この問題を説明するサンプル コードを次に示します。
/******************************************************/
import static org.hamcrest.Matchers.is;
import mockit.Expectations;
import org.testng.annotations.Test;
public class PrimitiveMatcherTest {
private MyClass obj;
@Test
public void testPrimitiveMatcher() {
new Expectations(true) {
MyClass c;
{
obj = c;
invokeReturning(c.getFoo(with(is(false))), "bas");
}
};
assert "bas".equals(obj.getFoo(false));
Expectations.assertSatisfied();
}
public static class MyClass {
public String getFoo(boolean arg) {
if (arg) {
return "foo";
} else {
return "bar";
}
}
}
}
/******************************************************/
invokeReturning(...) の呼び出しを含む行は NullPointerException をスローします。
次のように、この呼び出しをマッチャーを使用しないように変更すると、次のようになります。
invokeReturning(c.getFoo(false), "bas");
問題なく動作します。実際のコードでは複数パラメータのメソッドをモックしており、別の引数に対してマッチャーを使用する必要があるため、これは私にとっては役に立ちません。この場合、Expectations クラスでは次のことが必要です。 全て 引数はマッチャーを使用します。
これはバグであると確信しています。あるいは、プリミティブ型で Matcher を使用することはできないのかもしれません (それは私にとって悲しいことです)。この問題に遭遇した人がいて、回避方法を知っている人はいますか?
解決 2
したがって、問題は Expectations.with() にあるようです。
protected final <T> T with(Matcher<T> argumentMatcher)
{
argMatchers.add(argumentMatcher);
TypeVariable<?> typeVariable = argumentMatcher.getClass().getTypeParameters()[0];
return (T) Utilities.defaultValueForType(typeVariable.getClass());
}
typeVariable.getClass() への呼び出しは作成者が期待する動作を行わず、Utilities.defaultValueFor 型への呼び出しは null を返します。プリミティブ ブール値に戻すオートボクシング解除が NPE の由来です。
invokeReturning(...) 呼び出しを次のように変更することで修正しました。
invokeReturning(withEqual(false)), "bas");
ここではもうマッチャーを使用していませんが、必要なものには十分です。
他のヒント
問題は、Expectation の使用法と Matchers がプリミティブ型をサポートしていないことの組み合わせです。
Matchers コードは、基本的にプリミティブ型をサポートしない Generic に依存しています。通常、Matcher は値を照合するために使用されます。Java 5 の自動ボックス化/アンボックス化機能を使用すると、これは通常は問題になりません。
しかし、JMockit の Expectation は、値の照合にそれを使用するのではなく、メソッド呼び出し署名のタイプを決定するための何らかの解析に使用します。この場合、メソッドがプリミティブ型であるにもかかわらず、Matcher はブール型を結果として返します。そのため、失敗します。適切に嘲笑するために。
申し訳ありませんが、これに対する回避策をお伝えすることができません。もしかしたら他の誰かが助けてくれるかもしれません。
JMockit (リリース 0.982) を変更して、「with(is(false))」および他の同様のバリエーションが期待どおりに動作するようにしました (null を返すのではなく、内部マッチャー内の実際の引数値を返すようになりました)。