Since version 0.2.0, the detection of link between classes has been enhanced.
Conceptually, for every fields or parent classes, the annotation processor will try to find a Matcher to compare the values. This is done by detecting the relation between the class in compilation, but also by looking for existing Matcher (new in version 0.2.0).
To understand this concept, let's assume we have a first maven project, that use powerunit-extensions-matchers, with the following class annotated with @ProvideMatchers
:
Pojo1
Based on this class, a Matcher
class named Pojo1Matchers
will also be generated. This class will provide several DSL method, like :
pojo1With()
pojo1WithSameValue()
Now, we have a second maven project, which uses the first one as dependency, we have the following annotated classes :
Pojo4
which extends Pojo1
Pojo6
which have a Pojo1
field (named field1
)Based on these classes, several Matchers
classes will be generated :
Pojo4Matchers
- The annotation processor detects that the Pojo1Matchers
class is a valid Matcher
for Pojo1
event if it is already compiled.
pojo4With()
starts a DSL without check on the parent classpojo4With(org.hamcrest.Matcher<? super ch.powerunit.extensions.matchers.multi.parent.Pojo1> matcherOnParent)
starts a DSL with a matcher on the parent class. pojo4WithSameValue()
start a DSL to compare for same value. The pojo1WithSameValue()
from Pojo1Matchers
will be used for the control of the parent class.Pojo6Matchers
- The annotation processor detects that the Pojo1Matchers
class is a valid Matcher
for Pojo1
event if it is already compiled.
pojo6With()
starts the DSL. This DSL will provides a method field1With()
chaining to the pojo1With
DSL.pojo4WithSameValue()
start a DSL to compare for same value. The pojo6WithSameValue()
from Pojo1Matchers
will be used for the control of field1
.It is possible to create classes that may produce StackOverflowError
for the hasSameValue
matcher. This is the case with bidirectional class references or as a more generic case, circular references. It is almost impossible to detect these case at compile time ; For example, event if a class A
has a field of class B
and class B
a field of class A
, it is not possible to assume we have a bidirectional referencing (the issue is only when an instance of A
references a specific instance of B
and this instance of B
references the previous instance of A
.
In version 0.2.0, the easy way to break the cycle is to :
@IgnoreInMatcher
. The field will be ignored which will break the circular reference.Since version 0.3.0, an additional hasSameValue
methods is available to specify fields (based on field name) to be ignored. The previous option is still available, but it is also possible to use this ignore parameter. It is possible to chain the ignore by using a syntax like fieldName.fieldNameChildren
.
In case one of the referenced fields or the super class use an old version of the generated matchers and doesn't support the ignore feature, this feature is also not available on fields of the referenced fields or on fields of the super class.
Since version 0.3.0, the generated matchers try to detect the cycle. The hasSameValue
methods may detect the cycle and break it by replacing the deep reference with a sameInstance
Matcher. This feature is not able to detect cycle involving Map
, Collection
, Optional
or Array
.