hamcrest-pojo-matcher-generator
Inspired by lot of dummy work to create matchers for fields in auto-generated beans to write POJO-based tests.
Generates Hamcrest's Feature Matchers
for every field annotated with @GenerateMatcher annotation (ru.yandex.qatools.processors.matcher.gen.annotations.GenerateMatcher).
Useful for testing auto-generated unmarshalled beans with help of jsonschema2pojo + Gson or JAXB
Usage Guide
1. Add dependency from Maven Central
<dependency>
<groupId>ru.yandex.qatools.processors</groupId>
<artifactId>feature-matcher-generator</artifactId>
<version>2.0.0</version>
<!-- 'provided' scope because this is only needed during compilation -->
<scope>provided</scope>
</dependency>
2. Generate (or write) beans
@GenerateMatcher // works with class level annotations as every field with same annotation
public class Owner {
@GenerateMatcher
private String email;
@GenerateMatcher
private String uid;
@DoNotGenerateMatcher // excludes field from generation of matchers for class level @GenerateMatcher annotation
private String name;
public String getEmail() {
return email;
}
public String getUid() {
return uid;
}
}
Beans MUST have getters with named get[Field]() to generate working matchers
3. Compile
Run mvn clean compile
Also:
- Can use any other annotation to process if override system property
matcher.gen.annotations. - Can use multiply annotations comma-separated.
For example we have @Expose annotation (com.google.gson.annotations.Expose) by Gson
and want to generate matchers for fields with such annotation.
- Run compilation with
mvn clean compile -Dmatcher.gen.annotations=ru.yandex.qatools.processors.matcher.gen.annotations.GenerateMatcher,com.google.gson.annotations.Expose - Or put in classpath
matchers.gen.propertieswith contentmatcher.gen.annotations=ru.yandex.qatools.processors.matcher.gen.annotations.GenerateMatcher,com.google.gson.annotations.Expose
4. See generated matchers
You can find result in ${project.build.directory}/generated-sources/annotations/*.
For each class with such fields will be generated class *Matchers with public static methods looks like:
/**
* Matcher for {@link ru.yandex.qatools.beans.Owner#email}
*/
@org.hamcrest.Factory
public static org.hamcrest.Matcher<ru.yandex.qatools.beans.Owner> withEmail(org.hamcrest.Matcher<java.lang.String> matcher) {
return new org.hamcrest.FeatureMatcher<ru.yandex.qatools.beans.Owner, java.lang.String>(matcher, "email", "email") {
@Override
protected java.lang.String featureValueOf(ru.yandex.qatools.beans.Owner actual) {
return actual.getEmail();
}
};
}
5. Use it in your tests!
assertThat(someOwner, withEmail(containsString("@")));
// OR combined:
assertThat(someOwner, both(withEmail(containsString("@"))).and(withUid(is(uid)));
How to produce matchers in test scope for JAXB generated classes
There are 2 ways:
- Generate as usually in separate module and just add as dependency in
testscope - Generate all classes as test sources.
Generating JAXB classes and matchers as test sources
Add one more execution for
maven-jaxb2-plugin:<execution> <id>test</id> <phase>process-test-sources</phase> <goals> <goal>generate</goal> </goals> <configuration> <generateDirectory>target/generated-test-sources/xjc</generateDirectory> <addCompileSourceRoot>false</addCompileSourceRoot> <addTestCompileSourceRoot>true</addTestCompileSourceRoot> <args> <!--bunch of plugins that can be different from original configuration--> <arg>-enableIntrospection</arg> <arg>-no-header</arg> <arg>-Xxew</arg> <arg>-Xxew:instantiate lazy</arg> <arg>-Xfluent-api</arg> <arg>-Xinheritance</arg> <arg>-Xannotate</arg> <arg>-Xvalue-constructor</arg> <arg>-Xequals</arg> <!--in tests it will be useful to have to strings, equals...--> <arg>-XhashCode</arg> <arg>-XtoString</arg> </args> </configuration> </execution>If you want to add
toString,equalsetc methods, don't forget to add also dependency to test scope:<dependency> <groupId>org.jvnet.jaxb2_commons</groupId> <artifactId>jaxb2-basics</artifactId> <scope>test</scope> </dependency>Add dependency to annotaion processor to
<scope>test</scope>Add
matchers.gen.propertiesfile tosrc/test/resources/with content:matcher.gen.annotations=javax.xml.bind.annotation.XmlElement
How to debug Annotation Processors
With remote debugger on maven build
- Run in shell
export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n" - Run
mvn clean compile - Connect with remote debugger to port 8000
With Intellij IDEA
- Open
"Maven Projects"view - Disclose
"Yandex QATools Annotation Processors"element - Right-click on Maven phase
"package" - Click on
"Debug 'annotation-processors'"
It will create a new launcher configuration which can be used to debug project.
NOTE
Not supported: EmptyClass -> EmptyStaticNested -> StaticNestedWithFields
