Search code examples
javamavenhamcrestclover

How can I create reusable test code without creating circular dependencies?


Consider two projects.

  • mycompany-foo
  • mycompany-foo-tests

In mycompany-foo, I define some objects that I want to use in many other projects. In order to facilitate code reuse, mycompany-foo-tests defines hamcrest matchers that can match mycompany-foo objects.

The problem is that mycompany-foo-tests would depend on mycompany-foo in order for me to create a matcher for it. And then mycompany-foo would depend on mycompany-foo-tests so that I can do some matching within mycompany-foo's tests. This creates a circular dependency. Something I want to avoid.

I solved this problem by simply adding the matchers to mycompany-foo, removing the "tests" project, and exporting a test jar that contains the matchers as a "test-jar".

Everything was going smoothly until I learned that Atlassian's clover installed artifacts that it creates into my m2 repo[1]. This overrides my test-jar and causes downstream projects to fail when it can't initialize the clover version of my matchers.

The advice I see is to not create a test-jar, but rather go back to what I was doing before. That is, having a whole separate project for matchers. Is there a way to do that without creating a circular dependency?

[1] https://jira.atlassian.com/browse/CLOV-331


Solution

    1. Don't separate production code and its tests/test-utils into separate projects.
    2. Don't write matchers for your objects, there are tools that will do this for you (e.g. shazamcrest).