Patching a classpath when running Surefire tests - java

We are developing code in the context of a legacy Java application that heavily uses static members and system properties, expecting files in various locations on the disk. The builds are run in Maven.
We are trying to allow unit testing of our code without having to deploy, configure and start the whole application. I have managed to do this by patching a small number of classes in the framework, providing my own variants of the relevant source files in Maven's test sources in src/test/java.
As a next step I would like to make this patch re-usable by providing a JAR file that can be pulled in as a test dependency on any project that develops a part of the larger application. I would like to deploy this via our normal binary repository.
Surefire offers an option to set <additionalClasspathElements>, but according to the documentation this works only with absolute paths and will add the dependency at the end of the class path.
In theory ordering the project dependencies correctly could work, but I cannot find any documentation on how that order works across multiple scopes. I would need Maven to guarantee that my test dependency is loaded before the runtime ones.
What is a reliable way of patching classes for a Surefire run by using a JAR pulled via Maven's dependency resolution mechanisms?

Related

Maven dependency based on argument

I have a Maven project with a number of modules. When building, I have an argument that determines which directory config files and such are copied from, depending on environment it will be running in - ie UAT, DEV, TEST, etc. I do not want to use profiles. Now, I want to package all integration tests into a separate jar that can be executed from command line as well as in integration-test phase. Basically there will be only one test class with one method that does something like
Class.forName("...").getMethod("main").invoke(null, args);
Only problem, is that since I do not want to use profiles Id have to add/remove the dependency on the test solution jar depending on if I want to run integration tests or not. I would like to do something like
mvn clean install -Denv=IT
and let it be. Is there a way to do so?
The standard mechanism for running different kinds of build in Maven is to use profiles (Maven is a highly opinionated build framework, so you are forced to play by its rules)
Your also appear to be building binaries to match the system you intend to deploy. This is generally a bad idea, you are better advised to look at some mechanism that allows the run-time configuration of your application. (In J2EE there is JNDI, but could be just a simple property file). This allows you to certify a single binary that ideally is pushed into a shared repository for sharing between development, test and production.

Projects which are accessed via multiple (different) IDEs: Ant or Maven?

Is it true that one of the real benefits of Maven is that its projects structure is clearly defined and therefore it can be opened in any IDE that supports Maven?
We develop in a team consisting of 5 people and we use three different IDEs (IntelliJ, Eclipse, Netbeans). I know that I cannot open an Ant project of Eclipse in Netbeans but with Maven this is possible.
Is this really reason enough to use Maven?
Maven and Ant are two different things.
Ant is a build tool while Maven accumulates the functionality of:
resolving dependencies (you only specify the dependencies, and Maven cares about downloading them in the correct version from the default repositories on the i-net, or the ones you specified explicitly)
a build tool (incorporating Ant),
creating distribution artifacts (containing not only the jar/war/etc. file of the project but also dependencies, resources, documentation),
runtime environment (e.g. starting Jetty and deploying your artifact)
unit testing
integration testing
deployment (including signing, incrementing the version, deploying the artifacts etc.)
and more (look out for plugins on i-net)
Maven uses lifecycles to achieve this. You can trigger certain functionality at certain points in the lifecycle. For example unit tests should be run right after compiling while integration tests (e.g. selenium tests) require more setup, maybe initializing a web server and deploying the WAR file.

How to modify the Eclipse Run Configuration classpath?

I'm developing a project in Eclipse JDT, that has optional dependencies on OSGI - that is, it supports being used as an OSGI bundle, and if it is used as a bundle inside an OSGI environment, it will also reference some classes from OSGI.
Now I want to write JUnit test cases for both running inside OSGI and running without OSGI, included in two different test suites. The OSGI tests are run as JUnit Pulg-in Tests and the Non-OSGI tests should be run as normal JUnit Tests.
Now I have the problem, that I couldn't find any way in Eclipse to exactly specify the classpath for the JUnit Test Run Configuration and exclude the optional OSGI jars.
Is there any way to exclude jars or modify the default classpath for an Eclipse Run Configuration?
If not, does anyone have a suggestion, how one should setup JUnit tests in such a case?
The only solution I was able to find is, to create a jar file from my unit tests and run the tests without OSGI from a different project with the test jar file on the classpath. But I would prefer a more elegant solution, ideally without the necessity of a second test project.
With the help of Gimbys comment, I was able to solve the problem. Although it is not possible in Eclipse to modify the default classpath generated by JDT, it is possible to entirely remove the default classpath and then add your own classpath in the classpath tab of the Runtime Configuration.
To remove the default classpath, one has to select the root entry that is named after the currently run project, and then click on the "remove" button. After that one can add all the jar files and projects that should be loaded in the classpath. The downside of this approach is, that jar files, that are normally provided by Eclipse plugins like e.g. junit.jar, must then also be selected manually (e.g. by adding it to a library folder of the project or by selecting the external jar in the plugins directory of the Eclipse installation folder).
I would suggest that you split up your project in 4 separate projects:
Logic: This package contains all the logic, so basically what your program/plug-in does
Logic.plugin: This Project resembles a Plugin-Project (OSGI-Bundle). This project contains only configurations needed for your plugin and everything dependent on osgi. It has a dependency on your Logic Project.
Logic.plugin.test: All the test cases for your osgi bundle. It is the normal plugin approach to split up logic and test cases
Logic.cli: This project contains the command line interface (or whatever your alternate application is). This also depends on the Logic project.
If your CLI project is only very small you may merge it with the Logic project.

Source and test source in same project using Tycho

I have a question about Tycho packaging types and project structure. I currently have a project that has both source and test source directories following typical Maven convention, which is built using package type 'eclipse-plugin'. This results in tests not being run in the maven build. The most common solution I can find is to separate the test source to a project/bundle of its own and build that via 'eclipse-test-plugin'. My question: What are the drawbacks of keeping the Maven convention and just building the whole project as eclipse-test-plugin instead?
According to http://wiki.eclipse.org/Tycho/Packaging_Types:
"Tycho introduces new eclipse-test-plugin packaging type to represent such projects. Build behavior is like regular Eclipse plugins, but these are treated specially at test-time."
This makes me believe that there are actually no drawbacks apart from the resulting bundle possibly depending on bundles that are only required for the test source. However, this is also the case for building via 'eclipse-plugin' (without splitting). Is it safe to say that changing packaging type to 'eclipse-test-plugin' in this case only results in tests being run in the maven build with no other side-effects?
(...) there are actually no drawbacks apart from the resulting bundle possibly depending on bundles that are only required for the test source.
This is the main reason why there are separate eclipse-test-plugin modules for tests in Tycho.
There are no scopes in the OSGi manifest, so the test dependencies would pollute the dependencies of your productive bundle. When you then install your bundle into Eclipse or an RCP, it may pull in test bundles that your productive code doesn't actually need. For most users, this is enough reason to split their code into a productive and a test bundle.
Another potential reason for separating the tests is when you want to explicitly test via the OSGi API of your productive bundle. In this case, you would not use a fragment for the test, which ensures that your tests can only load classes from your productive bundle according to the OSGi package visibility rules.

Share entities between multi-projects

I have 3 Java projects with the same entities.
I want to share entities between these projects because entities can evolve during the development phase.
We are thinking about building a jar with entities and sharing it using Maven (with a repository).
Maybe you have another solution ?
I also can recommend to use Maven to share code between projects.
Here are some tips to get started:
Use a Maven Repository Manager such as Nexus. It will help you to
create a stable development environment.
Every developer (also the Continuous Integration Server user) should configure their settings file to use your Maven Repository
Manager. Don't specify your repositories in the POMs, confiugre them
only in your Maven Repository Manager.
http://www.sonatype.com/books/nexus-book/reference/maven-sect-single-group.html
Use the dependencyManagement and pluginManagement elements of your parent POMs to specify all versions of the plugins and dependencies
you are using. Omit these versions in the other POMs (they will
inherit them from the parent POM).
I also recommend to use different POMs for multi-module builds and parent POMs.
If you want to share common interfaces, classes, functionality or components, Maven is the way to go. In addition to the dependency management, you also get the added bonus of a standard project layout that will simplify things. Easy integration with most common continuous integration servers and a standard release process are further benefits.
Definitely take a look at Maven!
making an own JAR-library is definitely a good solution.
The jar-file is easy to distribute via dependency management (maven, ivy, gradle ..)
The jar is versioned
The projects using the library can be tested against a certain verion. Otherwise it may gets a problem if you change enties and forget to change a depending project. -> integration tests
Regards
Entities are the representation of a given object am I correct? If so the default mechanism implemented by Java is Object serialization - http://en.wikipedia.org/wiki/Serialization. In the case of jar files if an entity changes you would have to change jar once again each time as well. It may be tedious.
Geneate a standard war file in roo.. But then change it's package to jar file.
Then from any standard war file you can just deploy this jar (Ill use the jar as a maven dependency). Ill maintain a unique named applicationConext like pizzaShop-applicationContext.xml and like pizzaShop-applicationContext-jpa.xml. so from a parent spring project I can stack up various roo projects in this fashion.
Ill also keep their generated webapps folder to allow for the generator to work more easily. (This means I have to open up the pom.xml and keep changing it back to jar). Also helps with cut and paste fodder for non roo generated war files web.xml entry additions.
Seems like it may be a confusing point about roo.. You can just mix and match these jars as you would any spring project. They function like self contained units of springness and work fine sitting side by side with other spring jars all under the same webapp/web.xml context.
Its tedious but still better then writing spring code by hand.

Categories

Resources