Hai ragione a deridere l'API di elaborazione delle annotazioni (con una libreria di simulazioni come easymock) è doloroso. Ho provato questo approccio e si è rotto abbastanza rapidamente. Devi impostare su molte aspettative di chiamata di metodo. I test diventano non mantenibili.
A approccio test basato sullo stato ha funzionato per me abbastanza bene. Ho dovuto implementare le parti di javax.lang.model.* API I needed for my tests. (Che erano solo < 350 righe di codice.)
Questa è la parte di un test per avviare gli oggetti javax.lang.model. Dopo l'installazione, il modello dovrebbe trovarsi nello stesso stato dell'implementazione del compilatore Java.
DeclaredType typeArgument = declaredType(classElement("returnTypeName"));
DeclaredType validReturnType = declaredType(interfaceElement(GENERATOR_TYPE_NAME), typeArgument);
TypeParameterElement typeParameter = typeParameterElement();
ExecutableElement methodExecutableElement = Model.methodExecutableElement(name, validReturnType, typeParameter);
I metodi factory statici sono definiti nella classe Model
attuazione del javax.lang.model. * Classi. Ad esempio declaredType
. (Tutte le operazioni non supportate saranno generare eccezioni.)
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(); }
};
}
Il resto del test verifica il comportamento della classe in prova.
Method actual = new Method(environment(), methodExecutableElement);
Method expected = new Method(..);
assertEquals(expected, actual);
Si può dare un'occhiata allo source code of the Quickcheck @Samples and @Iterables source code generator tests. (Il codice non è ancora ottimale. La classe Method ha molti parametri e la classe Parameter non è testata nel suo test ma come parte del test Method. Dovrebbe comunque illustrare l'approccio.)
Viel Glück!