I am using Eclipse and Maven to build a project that is an excuse to try putting together some technologies I would like to get more experience with, and using ports and adapters (hexagonal) architecture. I am using Cucumber for Java as the testing framework, and I am trying to write the code using TDD & BDD. The project (in the general sense) consists of multiple Eclipse projects set up with the Maven nature.
Here is a list of the relevant Eclipse projects:
pricetracker.data
src/main/java - contains entity POJOs
src/test/java - empty
pricetracker.data.repo - depends on pricetracker.data
src/main/java - data access interface layer that defines the interface and factories for persistence
src/test/java - contains step definitions and step data (currently called StepData)
src/test/resources - contains Cucumber .feature files
pricetracker.data.repo.derby - depends on pricetracker.data.repo
src/main/java
src/test/java - contains a RunCucumberTest class, initializes the repo in StepData
pricetracker.data.repo.memory - depends on pricetracker.data.repo
src/main/java
src/test/java - contains a RunCucumberTest class
I believe I have all of the dependencies pointing correctly. However, the RunCucumberTest classes cannot see the StepData class (The import MyGroupId.pricetracker.data.repo.StepData cannot be resolved). And I cannot tell whether this is an Eclipse problem or a Maven problem.
Here is what the pom.xml looks like in pricetracker.data.repo.derby (replacing my actual groupId with myGroupId):
<dependencies>
<dependency>
<groupId>myGroupId</groupId>
<artifactId>pricetracker.data.repo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>myGroupId</groupId>
<artifactId>pricetracker.data</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.2.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Now if in pricetracker.data.repo I move StepData from the src/test/java folder to the src/main/java folder, it becomes visible from the pricetracker.data.repo.* subpackages RunCucumberTest files. However, this is not production code and should not be under src/main/java.
In Eclipse itself, in each project, the test folders are all marked as "Contains test sources: Yes" and are set to compile into a separate folder from the main classes.
Any pointers are appreciated!
Related
I'm trying to introduce Unit tests to our system, and have run into a problem with Junit not finding test.
I have these 3 tests:
When I run all tests in the module:
It finds X and Y tests, but not Z:
The difference between the 3 is only in the package name:
The package com.exlibris.x (XTest) doesn't exist in the project
The package com.exlibris.core.infra.svc.api.flags (YTest) exists in a different module in the project (that is outputted to a different jar file)
The package com.exlibris.repository.web.mms.publishing (ZTest) exists in the same module under the src/main/java
My pom.xml has the following dependencies (inherited from the parent pom):
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
EDIT: These are my run configurations
So it turned out there were a few issues (some of them are likely not related to the specific question, but still best practices).
What helped for me was:
Consolidate dependency management of JUnit by importing junit-bom
Upgrading maven-surefire-plugin to latest version
Removing unnecessary configs from maven-surefire-plugin (my configuration tag is now empty)
Reloading the project in IntelliJ (Right click project -> Maven -> Reload project)
Thanks a lot to khmarbaise and Kathrin Geilmann for the help :)
Eclipse (2018-09) supports JUnit 5 tests only if the JUnit 5 engine is present on the classpath of the project.
Now I have two possibilities in my Maven project:
Add it to the project via an eclipse JUnit Library
and add only the API to the dependencies
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
Add both the engine and the API to to my Maven pom
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
If I do the former, then everybody using eclipse has to do this himself.
If I do the later, then I pollute my (test) compile time classpath with implementation classes, that I (and users of other IDEs) might use instead of the API classes. Also this might cause conflicts with the IDE that might need a different version of the engine, than the one on the cp. IIRC that was the whole point why API and engine have been split up in the first place.
Unfortunately there is no testRuntimeOnly scope in Maven (like there is in gradle).
TLDR: Which way is the correct way to configure JUnit 5 for eclipse for a Maven project?
If I do the former, then everybody using eclipse has to do this himself.
I assume you intended to give an eclipse user a chance to execute a test by right clicking a JUnit test class and selecting Run as > JUnit Test. I don't know if this is the right way but to do so you need to add an additional dependency besides JUnit Jupiter API/Engine, which is JUnit Platform Launcher.
For example:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.4.2</version>
<scope>test</scope>
</dependency>
Not sure if its related but I am using maven-surefire-plugin Version 2.22.1 which throws ClassNotFoundException if JUnit Platform Launcher is missing.
In Eclipse, when I go to myProject -> right click -> Run As -> Maven build, I am getting multiple errors in the console outlining that certain packages does not exist, like:
javax.ws.rs does not exist
javax.ws.rs.core does not exist
javax.servlet does not exist
javax.servlet.http doest not exist
Although in my pom.xml, I have provided those dependencies:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs</artifactId>
<version>1.0</version>
</dependency>
etc
under
<dependencyManagement><dependecies>
tags (don't have any errors in pom.xml).
I do also have proxy settings configured in settings.xml file, and this file is properly linked.
I've also got these jars included locally to WebContent\WEB-INF\lib folder and added to the classpath (I can run my REST service on tomcat, the error "package does not exist" appears only when I am trying to use Maven build".
The reason I need that I want to generate and deploy a .war file.
How I can solve this? Is there a war to force Maven look in local libraries instead?
If you have:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
then you need to have a separate:
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs</artifactId>
</dependency>
</dependencies>
section.
Typically you would define dependencyManagement in a parent pom.xml file and then use the second dependencies fragment in child pom.xml files. This ensures that all your modules depend upon the same consistent artifacts.
I created a word count project and import with maven the GeoIP by maxmind(maven) - this Geoip project is build with maven.
After I import I have a new project(geoIP) next to word count project with a pom.xml (very long) which was created by eclipse .
But in the above link they are saying add to pom.xml
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>v2.3.0</version>
</dependency>
I don't get it if eclipse created pom.xml for me should I delete OR add it with the above code ?
How many pom.xml files do I need ?
Does MapReduce project needs to be built with maven as well ?
I haven't worked with GeoIP2 but it shouldn't make a difference here.
if eclipse created pom.xml for me should I delete OR add it with the above code ?
Eclipse created a pom.xml file for your geoip project by default. You should add your new dependency for your file in order to access GeoIP.
How many pom.xml files do I need ?
Really depends on your overall project structure. You should probably take a look at the answers of this SO question and take a peek at this example of multiple maven files for a project.
Does MapReduce project needs to be built with maven as well ?
Nope but I would recommend it, it makes your life easier. Here are my dependencies for Map-Reduce Jobs:
<dependencies>
<!-- junit testing framework -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- hadoop hdfs components -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.1</version>
</dependency>
<!-- hadoop map-reduce components -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.1</version>
</dependency>
<!-- hadoop common components -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.1</version>
</dependency>
</dependencies>
With all additional dependencies located in the Maven Repository for Hadoop.
I have a project with multiple Maven dependencies and want to minimize the size of my compiled JAR. Right now it seems that IntelliJ is compiling all of the external dependency source files into my JAR even though I only use a small subset of their functionalities.
I would like to include only the files that are directly used by my module.
You can declare a dependency as optional:
<dependencies>
<dependency>
<groupId>sample.dependency</groupId>
<artifactId>small-dependency</artifactId>
<version>1.0</version> <!-- Will be packaged in JAR -->
</dependency>
<dependency>
<groupId>sample.dependency</groupId>
<artifactId>really-big-dependency</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
</dependencies>
Another approach is to use the provided scope. The difference is provided is used if you know the dependency will be included in the classpath of the application that will run your JAR (e.g. a Web or Java EE container):
<dependencies>
<dependency>
<groupId>sample.dependency</groupId>
<artifactId>small-dependency</artifactId>
<version>1.0</version> <!-- Will be packaged in JAR -->
</dependency>
<dependency>
<groupId>sample.dependency</groupId>
<artifactId>really-big-dependency</artifactId>
<version>1.0</version>
<scope>provided</scope> <!-- Will not be packaged in JAR, needs to be provided in classpath at runtime -->
</dependency>
</dependencies>
Sources:
Maven - Optional Dependencies and Dependency Exclusions
Maven - Dependency Scope