アノテーション処理API(easymockのようなモックライブラリを使用)をモックするのは苦痛です。私はこのアプローチを試しましたが、かなり急速に崩壊しました。多くのメソッド呼び出しの期待に合わせて設定する必要があります。テストは保守できなくなります。
状態ベースのテストアプローチは、私にとってはかなりうまくいきました。テストに必要なjavax.lang.model。*APIの一部を実装する必要がありました。(それはたった350行未満のコードでした。)
これは、javax.lang.modelオブジェクトを開始するためのテストの一部です。セットアップ後、モデルはJavaコンパイラの実装と同じ状態になります。
DeclaredType typeArgument = declaredType(classElement("returnTypeName"));
DeclaredType validReturnType = declaredType(interfaceElement(GENERATOR_TYPE_NAME), typeArgument);
TypeParameterElement typeParameter = typeParameterElement();
ExecutableElement methodExecutableElement = Model.methodExecutableElement(name, validReturnType, typeParameter);
静的ファクトリメソッドはModel
、javax.lang.model。*クラスを実装するクラスで定義されます。たとえばdeclaredType
。(サポートされていないすべての操作は例外をスローします。)
public static DeclaredType declaredType(final Element element, final TypeMirror... argumentTypes) {
return new DeclaredType(){
@Override public Element asElement() {
return element;
}
@Override public List<? extends TypeMirror> getTypeArguments() {
return Arrays.asList(argumentTypes);
}
@Override public String toString() {
return format("DeclareTypeModel[element=%s, argumentTypes=%s]",
element, Arrays.toString(argumentTypes));
}
@Override public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitDeclared(this, p);
}
@Override public boolean equals(Object obj) { throw new UnsupportedOperationException(); }
@Override public int hashCode() { throw new UnsupportedOperationException(); }
@Override public TypeKind getKind() { throw new UnsupportedOperationException(); }
@Override public TypeMirror getEnclosingType() { throw new UnsupportedOperationException(); }
};
}
テストの残りの部分では、テスト対象のクラスの動作を検証します。
Method actual = new Method(environment(), methodExecutableElement);
Method expected = new Method(..);
assertEquals(expected, actual);
Quickcheck@Samplesおよび@Iterablesソースコードジェネレーターテストのソースコードを見ることができます。(コードはまだ最適ではありません。Methodクラスには多くのパラメーターが必要であり、Parameterクラスは独自のテストではなく、Methodテストの一部としてテストされます。それでもアプローチを説明する必要があります。)
VielGlück!