Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving Maven circular dependencies between test, testhelper, and project-under-test

my set up is this. I have project A, and a test project depending on A:

A <- A_t

I also have other projects depending on A (and their tests):

A <- B <- B_t

To simplify some of the testing I introduce a new library helping test stuff based on A:

A <- Atesthelper

So A_t (and B_t) will depend on this test helper, like this:

A <- A_t
^    |
|    v
Atesthelper

However when I create Maven projects (pom.xml) it seems the usual thing is to bundle both the project and the test of that project in the same pom.xml. And I create a new pom.xml for the Atesthelper

So now it becomes:

(A <- A_t)
  ^    |
  |    v
Atesthelper

Which is a circular dependency. Is it possible in the pom.xml to somehow specify that Atesthelper is only a dependency of the test build target, and not the A module in itself?

So the build order should be: A, Atesthelper, A_t. I.e. A and A_t which are specified in the same pom, should not be build at the same time.

Thanks in advance.

like image 732
Bjarke Freund-Hansen Avatar asked Apr 16 '12 12:04

Bjarke Freund-Hansen


People also ask

How do you resolve cyclic reference in Maven?

Maven does not allow cyclic dependencies between projects, because otherwise it is not clear which project to build first. So you need to get rid of this cycle. One solution is the one you already mentioned, to create another project.

How can circular dependencies be avoided?

Circular dependencies can be introduced when implementing callback functionality. This can be avoided by applying design patterns like the observer pattern.

What's wrong with circular dependencies?

Cyclic dependencies between components inhibit understanding, testing, and reuse (you need to understand both components to use either). This makes the system less maintainable because understanding the code is harder. Lack of understanding makes changes harder and more error-prone.


2 Answers

If I understand you right, your primary goal is to reuse test classes. A_t and Atesthelper are not Maven projects, they are tests.

Make Maven to create a jar from your src/test/java. See http://maven.apache.org/guides/mini/guide-attached-tests.html

After build of A you will get A.jar and A-tests.jar. A-tests.jar will include Atesthelper and A_t.

Set dependency of B to A-tests.jar (<type>test-jar</type>).

like image 135
Aleksey Otrubennikov Avatar answered Oct 10 '22 06:10

Aleksey Otrubennikov


The problem that you need to solve is the dependency from Atesthelper to A, then everything else will work fine: A depends on Atesthelper, B depends on Atesthelper and both A and B will contain both sources and tests. Atesthelper will be included with scope test in both A and B. That's your target state.

How do you get there? You need to extract the items that Atesthelper is depending on into a separate projects. Typically, these are interfaces or other common functionality, which should be put into a separate project anyway - let's call it ACommon. So your target layout should look like this:

ACommon <- Atesthelper
       ^    ^
       |   /
         A (and also B)

What kind of functionality is Atesthelper depending on in A? Can you move it to a separate project (ACommon)?

like image 31
nwinkler Avatar answered Oct 10 '22 07:10

nwinkler