Testing in Maven - maven

So I have a project in Maven, with the tree structure it made and the code completed.
Now Im in the test phase and supposedly (if I am not wrong) I have to use the AppTest.java in the test branch of the project.
The thing is that the classes I need to test are in the "main" branch of the project.
How do I import them so that the test can be performed?
EDIT:
Yes, with branch I wasnt referring to anything version control related but about the location in the folders maven autogenerates (given the tree view of the folders used by Eclipse).
ANSWER:
As Aaron Digulla said, I could import them as usual.
It was enough with "import domain.NameOfClass;"
It complained about not being able to autocomplete the route when I typed the dot, but ignoring it was the way to go since it ended up working.
Maven took care of that.

Just import them as usual. When running the tests, Maven will create a classpath which will make everything in src/main/java visible to the test classes.

Related

Maven: How to manage test code module dependencies

We've migrated an ant project (codename one) to a maven project which happened through a migration tool. Unfortunately there is still a problem. Somehow, the test source directory (set via testSourceDirectory in pom.xml) becomes part of the wrong module (it is at least shown so in the project view of IntelliJ IDEA). Therefore the test source code is missing neccessary core dependencies. The core code (actual implementation) is in the "common" module. Even though the test code is located (in IntelliJ) under the "common" module, it is itself marked as being part of the "cn1libs" module. We have no idea, how the ide or maven concludes this from the pom config.
snippet from the pom:
<testSourceDirectory>${project.basedir}/common/src/test/java</testSourceDirectory>
the dependencies in the test sources can't get resolved
How can we fix this?
Sometimes IntelliJ will give you erroneous labels like this if there is more than one module that references that directory in their pom file. Check your cn1libs/pom.xml file and make sure that it doesn't have <testSourceDirectory> specified anywhere. Its packaging type should also be pom.
Codename One projects are set up to do unit tests using the Codename One test runner. It uses its own "test" goal. You are importing junit's Test class which may be problematic here unless you really know what you are doing. E.g. The Codename One testrunner will set up the test environment and run the tests in a simulated environment. Junit will just run them raw.
If you need to add test dependencies, however, you should be able to just add them in the dependencies section of the common/pom.xml file, just make sure you set the dependency scope to "test".

Why refresh of Maven repository is not enough for IntelliJ?

I had a NoClassDefFoundError problem with some test, launched from IntelliJ. In order to repair the situation, I had to make several changes in many poms of the project - adding new packages and excluding some old ones for to escape the overlapping of them. Also, I reapired the situation with different versions. But the situation did not improve. Again, some package, declared in pom, was not found where it should be.
I refreshed the maven repository by
mvn -e clean install -U
, as is advised in https://stackoverflow.com/a/9697970/715269 - so old and upvoted answer, that it surely looks as Santa.
The problem remained unchanged.
I output the maven map. It was correct and it contained all needed.
I looked at the list of the External Libraries of the project. It was the old uncorrected list of overlapping jars with same names and different versions, and without good packages I added just now, and well seen in maven tree output!
Already hapless,
I reimported packages in IntelliJ
by:
Ctrl+Shift+A, Reimport All Maven Projects.
Ho! The list of libraries got repaired. And the problem, mentioned in subj, disappeared.
The question is: How it could happen, that the same project has that very pom for everything, but gets packages differently being launched in maven and in IntelliJ?
I know about that feature "delegate IDE build to Maven". And I keep it turned off. But I am NOT talking about the different SW for building. Whether they are different or not, they should be up to the actual pom's. And whereas maven, if turned off from the automatic building won't know about changes in poms, IntelliJ KNOWS about them. It could have jars up to pom, or up to maven - it has sense, but it simply has some old rubbish. Was there some deep thought under that construction?
Every time you manually change the pom.xml file, including the dependencies you need to load these changes into IDE. IDE does it on Reload from Maven action. See also Import Maven dependencies.
Intellij doesn't use maven to bulid and run a project except you are delegating build and run action to maven:
Since, IDEA doen't really use maven to run and build, it uses the pom.xml to import the project structure and "tries" to build the project the same way was maven does.
Actually, there are quite a few differences between these to build processes.
Generating sources or filtering resources (don't know if this is still an issue) aren't done during building the project with Intellij IDEA.
In case you are using code generation you have to build the project via maven first and then - when all the resouces are filtered and additional sources are generated - you are able to run, debug aso. the project with Inellij IDEA.
That's an important thing to be aware of and that's the reason why maven and IntelliJ IDEA project structures might get out of sync.
You can enable the "Reload project after changes in build scripts" feature and select the Any changes checkbox to keep your project structure updated:
Why should you disable this feature anyway
If you are working on a build file (gradle or maven is not important) reloading the structure on any change can be very anoying. It's cpu intense, dependcies are fetched aso.
Therefore, I prefer to reload project structure only in case of an external change. This happens when pulling an updated version of the build file for example.

How to link individual Java classes to jars displayed by dependency:tree?

Is there a way to easily link a specific Java class to a jar that is listed by mvn dependency:tree? I tried -X to and -Dverbose to add verbosity but it didn't do it.
I have an import statement that I suspect is pulled from one jar in one version of my pom and from another when I change some dependency declarations in the pom because the API becomes different. But I know of no easy way to trace the imported class to a jar in the dependency tree.
To locate the maven dependency for a specific import, I usually do a Go to -> Declaration (⌘B on OSX) followed by clicking the Scroll from Source button in the Project tab like so:
I noticed that the first time I did this, the source for junit-3.8.1 was not present in my local maven cache due to which, Intellij IDEA decompiled the Testcase class. The Scroll from Source did not work for this de-compiled source. However after clicking the Download Sources and retrying the Scroll from Source worked fine as above.
This approach has stood me well for checking the maven dependency which is the source of that one off import.

Maven module dependency source instead of repository jars

I have a multi-module project, i.e.
parent
module1
module2
In one dev cycle, I added a class mod1.A to module1. Class mod2.B in module2 depends on it.
I do not have the artifacts in my local .m2/repository. Running this:
$ cd prj/module2
$ mvn -o exec:java -Dexec.mainClass=mod2.B
results in an error along the lines of:
The following artifacts could not be resolved: com.example:module1:jar:1.0-SNAPSHOT
After I install the artifacts via mvn install while in the prj folder, it all works as expected.
However, this presents an issue in at least two ways:
I have to go through the slower install phase instead of the faster compile phase
I have two versions of the same project and conflicting modifications in these. I cannot run the same Java class with their respective modifications, only the currently installed modifications, considering they are both the same SNAPSHOT version
There are workaround for both (skip parts of the build for the first, different snapshot versions for the second), but they are far from usable in practice.
Is there a way to make maven use the local modules, instead of using artifacts from local maven repository?
If I understand your question correctly, it seems like you are living a bit outside the norm here: you have two local "copies" of the project with different modifications, that you want to work with alternately when running "exec:java". And Maven is getting in your way: it expects your local .m2 repository area to be in play, but the version strings in each copy are the same, so you end up with the changes interfering among the copies.
To me, it sounds like what you are trying to do is to test your changes. I suggest you just write an actual JUnit or TestNG test in module2 that tests what you want (it can just call mod2.B Main if you want). Then, from your chosen project directory, you can run mvn test -Dtest=MyTestName. It won't "install" anything and it will find the dependencies the way you want it to.
Otherwise, I can see three options.
Change the version string locally in one of the copies (mvn versions:set -DnewVersion=B-SNAPSHOT can do this for you). That way any "installed" jars from your work on that copy will not be considered by the other copy, and vice-versa. You refer to this as being "far from usable" ... I think it should be fine? These are different versions of the project! They should have different version strings! I strongly recommend this option out of the three. (You can do mvn versions:revert when done if you used :set, or you can rely on version control to undo the change.)
Select a different local repository used by Maven when working on one of the projects, with a command-line flag as per https://stackoverflow.com/a/7071791/58549. I don't really think this is a good solution, since you would have to be very careful about using the right flags every time with both projects. Also you'd end up having to re-download Maven plugins and any other dependencies into your new local repository anyway, which is kind of a waste of time.
Try to avoid using any local repository at all. You seem to be trying to make this option work. I don't think this is a great approach either; you're fighting against Maven's expectations, and it limits your flexibility a lot. Maven will indeed find dependencies from the "reactor" (i.e., the executing mvn process) first, but this means all of the required modules must be available in the reactor to be found, which means you can only run mvn at the top level. So if instead you want to just do "mvn exec:java" inside a single module, mvn needs to find that module's dependencies somewhere ... and that's what the local repo is generally used for.
If you're dead set on going with option 3 (instead of option 1), then I suggest you follow the comments on your question and create a profile that runs your exec selectively against module2 and binds it to a lifecycle phase. But this is in practice very close to just wrapping it with a test.
For IntelliJ users:
I solved this problem using IntelliJ's Run configuration. It has the options Resolve workspace artifacts and Add before launch task -> Build. See this picture for clarification:
Run configuration example
The whole point of modules in Maven is to create decoupling between them. You either build each module independently, so that you can work on one module without touching the other, or include both modules as sub-modules in the parent pom and build the parent, which will resolve dependencies between its sub-modules and trigger their builds.
It looks like you have two options here:
Review the structure of your project. Do you really need to split it into two separate modules, if you change code in both of them simultaneously?
Import the project into a Maven-aware IDE (IntelliJ IDEA is very good at working with Maven), and let the IDE handle the compilation. Once finished and stabilized the code-base, build normally with Maven.

Difference between the main and the test folder in Maven

I am a bit confused on the difference between the use of the folder main and the folder test in Maven. As of now, I just copy and paste my source code in both of them and it works fine. I don't get what the point of having another folder with exactly the same thing as the main folder is? Can someone please explain this to me.
Also:
What is the difference between install and compile.
So for this command: mvn archetype:generate, is generate the goal? then what is archetype?
Thanks
The main folder contains your application code and resources, and the test folder contains, well, test code and resources. So don't copy your application code there, but only the tests. The test sources are then automatically added to the classpath in the test phases.
For the difference between install and compile have a look at https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html. Basically install also contains compile and a lot more goals (like execution of tests, packaging, installing into local repository.
generate would be the goal, correct. archetype is the short form for maven-archetype-plugin and means the plugin, which contains the goal. By default plugins with the name pattern maven-*-plugin or *-maven-plugin can be shortened that way.
Separation between src and test folders is a standard practice where same package structure under both guarantees your com.some.Class finds its way and it's visible when com.some.ClassTest unit test runs.
Difference between install and compile. Read the documentation around the Maven lifecycle. Essentially everytime you are invoking one build phase, every other build phase defined before it in the lifecycle gets called in the defined order.
Documentation about what is Archetype

Resources