I've got a Java project in Maven with the following (simplified) structure:
module-alpha
src
main
test
java
TestUtils.java <-----------------------
module-beta
src
main
test
java
TestUtils.java <-----------------------
...
module-yotta
src
main
test
java
TestUtils.java <-----------------------
There is a class TestUtils.java repeating itself along the project. (It's a simple class I wrote as a library for needed stuff in every unit test.)
How can I avoid this code redundancy?
You need to create a different maven project that include TestUtils.java and build it as a jar e.g. test.jar.
Then use test.jar as a local dependency of relevant projects.
Related
The Description:
I would like to create a JUnit test using JUnit 5 in Eclipse (Oxygen 4.7.1a).
This JUnit test should be inside a seperate src folder called Test. However, I ran into the following problems as I'm new to JUnit and Java 9.
I do not want to use build tools like Gradle or Maven for this.
The Problem:
As I've got two different src folders, one for the projects src and one for the test cases:
Do I need two module-info.java files? (one for each src folder)
Which modules are required in my module-info.java file for JUnit 5 to work?
In general there is no need to modularize your test code (at least I can't think of a valid reason, maybe someone could give a satisfactory counter-example). Only one module-info.java file can (after all, it's not even required to modularize your main code) be present in your main code under src.
Since the module-info.java file will be only in your main source directory and not in the test source directory, then logically it should not depend on the JUnit module. So the questions now become how to compile and run the JUnit test classes by relying on the module (that represents the system under test) and the JUnit module.
To do that, you'll need to use the new options provided by the javac and java:
So assuming you have the following tree:
src
module-info.java (declares a module called "my.module")
mypackage
MyClass.java
test_src
mypackage
MyClassTest.java
lib/junit-platform-console-standalone.jar
(note: specifically for JUnit 5, you can use the junit-platform-console-standalone artifact that contains the core JUnit engine and allows running tests in the console; see the user guide)
then you can compile the code as follows:
cd root_dir
javac -d mods/my.module src/module-info.java src/mypackage/MyClass.java
cd test_src
javac -d test_out --module-path ../mods;../lib/junit-platform-console-standalone.jar \
--add-modules org.junit.platform.console.standalone,my.module --patch-module my.module=. \
--add-reads my.module=org.junit.platform.console.standalone mypackage/MyClass.java
and you can run the compiled test class:
cd test_src/test_out
java --module-path=../../mods;../../lib/junit-platform-console-standalone.jar \
--add-modules my.module,org.junit.platform.console.standalone \
--add-reads my.module=org.junit.platform.console.standalone \
--patch-module my.module=. \
--add-opens my.module/test=org.junit.platform.console.standalone \
org.junit.platform.console.ConsoleLauncher test.MyClassTest
Awkward commands but that's the cost of not using Maven. I advise you to read about these options in the command documentation after understanding the concept of a module path. An important thing to note here are a couple of options:
--patch-module my.module=.
This is needed because the example test code has the same package (mypackage) as the module my.module. Without it, the module system will complain.
--add-reads my.module=org.junit.platform.console.standalone
This makes junit required by my.module even though it was not declared in module-info.java.
org.junit.platform.console.standalone is the name of the automatic module and is derived from the Jar manifest (as is the case with JUnit 5), otherwise from the name of the Jar file (e.g. in the case of JUnit 4).
Also note that this is what Maven probably does behind the scenes when compiling and running unit tests (see this issue for an equivalent plugin configuration that manually does the above).
What if for some reason, you also want to modularize your unit tests?
In this case, since in the example above the unit tests share the same package, you can include them in my.module and add a requirement to JUnit:
module my.module {
exports mypackage;
requires org.junit.platform.console.standalone;
}
If the unit tests were in a different package, you can also split them into two modules (two module-info.java), a my.module and a my.test.module where only the latter requires JUnit.
If you do include test classes in a module, then in the above commands, you don't need --add-reads and --patch-module.
A reason for the tests being in a module on their own is hexagonal architecture. The test module is a driver adapter swappable with other adapters that run the business logic too.
In my case I'm gonna do it using jaba 9 without maven too.
Here's my article about hexagonal architecture:
https://softwarecampament.wordpress.com/portsadapters/
MyProject/build.sbt
mainClass in assembly := Some("Boot")
MyProject/Boot.scala
package src.main.myproject
object Boot extends App { ... }
Other Project Files:
MyProject/src/main/scala/myproject/someFile.scala
Running the jar returns the error:
Error: Could not find or load main class Boot
Is there a problem with my project structure?
Your Boot is in src.main.myproject, so the mainClass should be src.main.myproject.Boot
Off topic in terms of the question, but it doesn't seem conventional that src.main is part of your package structure though, normally scala src directory of sbt is set to src/main/scala
I am currently trying to introduce unit tests to a legacy project based on ant. The problem is that the project's structure is a little unconventional: Java files mixed up with xml files in the same directory, there are multiple java source directories, the Java files depend on import jars wich are not present in the same project ...
What is a clean way to introduce unit tests to a project with this structure:
--->project
----->folder1
----->folder2
-----file1.java
-----file2.xml
-----file3.prop
----->folder3
I'd probably do it like:
--->project
----->folder1
----->folder1-test
----->folder2
-----file1.java
-----file2.xml
-----file3.prop
----->folder2-test
-----file1Test.java
-----file2Test.xml
----->folder3
----->folder3-test
Or bite the bullet and refactor using maven conventions
folder1/src/main/java
folder1/src/main/resources
folder1/src/test/java
folder1/src/test/resources
etc...
I'm working on a maven-spring-web project in Eclipse. I am getting some problem working with jUnit tests, it seems to me a configuration issue.
Project structure:
src > main > java : business logic goes here
src > test > java : jUnit test cases are parked here.
The trouble is that imports are not working when im trying to import some business logic classes from src>main>java into my jUnit test cases. The reason is that the physical folder structure is :
Business logic classes : project_root > src > main > java
Test cases classes : project_root > src > test > java
I've tried cleaning, putting testResources directory in POM. I dont want to add classes folder in classpath. Pls advise.
You can't use default package in src/main/java, try to new a package and you can import the class then.
By default Maven uses the following naming conventions when looking for tests to run:
Test*
*Test
*TestCase
Your test class doesn't follow these conventions.
This is a relatively open question. If I have built an application in a project in Eclipse and I then want to test this project, should I create the JUnit code within the same project or create a separate project. For instance...
ShopSystem maybe the name of my main project - should I create a project called say, ShopSystemTest?
In general - how far "away" should the testing code be stored from the main project folder? If I store the testing code within the main project and then export the main project as a runnable jar it will take the testing code with it, which isn't ideal...
Suggestions?
While there is no only right way, the usual approach is to keep unit tests in the same project.
You can create a second source folder (like test), where you put your test classes into the same packages as the classes under test. This also allows you to test package-private classes while not flooding your main source packages with test classes.
Your source folder/package structure would then look like this:
-sources
-main
-my.package
-MyClass.java
-test
-my.package
-MyClassTest.java
You can then configure your build to not include the test source folder when packing the JAR.
I like the maven convention a lot: There is a separate source tree for main and test in the same project, main code gets deployed, test code doesn't. Package structures can be (but don't have to be) identical.
project
src
main
java // source files
resources // xml, properties etc
test
java // source files
resources // xml, properties etc
And in eclipse, when you choose new -> JUnit test case, you just change the source folder to src/test/java and leave the suggested package as is.
(One of the benefits of remaining in the same package is having access to protected and package scoped members, although this is not 'proper' unit test behavior)
Update: Here's some code to illustrate my last point:
Main class (in src/main/java):
package com.test;
public class Foo{
static class Phleem{
public Phleem(final String stupidParameter){
}
}
String bar;
protected String baz;
protected Object thingy;
}
Test class (in src/test/java):
package com.test;
import org.junit.Test;
public class FooTest{
#Test
public void testFoo(){
final Foo foo = new Foo();
foo.bar = "I can access default-scoped members";
foo.baz = "And protected members, too";
foo.thingy = new Foo.Phleem("And I can access default-scoped classes");
}
}
Typically you have -
/src/main/java (for codes)
/src/test/java (for tests)
Consider the maven way : In a maven project, soruces are organized this way
src
|--main
| |--java
|--test
|--java
Your source code goes in src/main/java, your junit test code goes in src/test/java, they both are source folder (and as a consequence you can put your jUnit code in the same package as your Java code, but in a different source folder).
The interest is that for usual coding, your jUnit classes are in code packages, but on jar creation, you can take classes coming only from src/main/java and not release your tests.