Problems with setting up a trivial jmockit test with maven - java

Today I've spent some non-zero time trying to setup a simplest maven project that will run a simplest jmockit test.
While trying to write such an xml, I've faced with several problems, starting with
java.lang.NoClassDefFoundError: org.junit.runner.Runner
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:61)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
....
and later having problems with running it.
Unfortunately attempts to find quick answer using google didn't help.
So, what it the smallest pom.xml for using jmockit framework with maven?

At the end I came up with a working pom.xml which I want to share - probably this will be useful for someone.
$ cat pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>jmockit-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<argLine>-javaagent:"${settings.localRepository}"/org/jmockit/jmockit/1.17/jmockit-1.17.jar</argLine>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
</project>
And source files are:
$ cat src/main/java/com/test/jmock/DataProvider.java
package com.test.jmock;
public interface DataProvider {
Integer getInt();
Boolean getBoolean();
}
and
$ cat src/test/java/com/test/jmock/TrivialTest.java
package com.test.jmock;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public final class TrivialTest {
#Mocked
private DataProvider provider;
#Test
public void test() {
init();
Integer mockIntData = provider.getInt();
System.out.println("Mock int data is " + mockIntData);
assertEquals("Unexpected result", mockIntData, Integer.valueOf(12345));
Boolean mockBoolData = provider.getBoolean();
System.out.println("Mock bool data is " + mockBoolData);
assertEquals("Unexpected result", mockBoolData, Boolean.TRUE);
}
private void init() {
new NonStrictExpectations() {
{
provider.getInt();
result = 12345;
provider.getBoolean();
result = Boolean.TRUE;
}
};
}
}
Now this works as expected!
$ mvn test
...
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 sec - in com.test.jmock.TrivialTest

I had the same problem. I used the answer from #andrew-krasny and modified it to use the other solution (-Djdk.attach.allowAttachSelf) so you don't have to update it when you update jmockit.
<build>
<plugins>
<!-- Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>10</source> <!-- was 1.8 -->
<target>10</target> <!-- was 1.8 -->
</configuration>
</plugin>
<!-- FIX START -->
<!-- Test -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<argLine>-Djdk.attach.allowAttachSelf</argLine>
</configuration>
</plugin>
<!-- FIX END -->
</plugins>
</build>

Related

maven unit test fails but passes independently [duplicate]

JUnit 5 does not invoke my method in a test class that is annotated with the #BeforeEach annotation, where I initialize some fields of the test object that are needed in the tests. When trying to access these fields inside a test method (method annotated with #Test) I obviously get a NullpointerException. So I added some output messages to the methods.
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TestClass {
private String s;
public TestClass() {
}
#BeforeEach
public void init() {
System.out.println("before");
s = "not null";
}
#Test
public void test0() {
System.out.println("testing");
assertEquals("not null", s.toString());
}
}
In the output of the tests when running mvn clean test I get the "testing" message from the test0() method annotated with #Test annotation, but the "before" message is not printed.
Running de.dk.spielwiese.TestClass
!!!testing!!!
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0 sec <<< FAILURE!
de.dk.spielwiese.TestClass.test0() Time elapsed: 0 sec <<< FAILURE!
java.lang.NullPointerException
at de.dk.spielwiese.TestClass.test0(TestClass.java:24)
The very obvious and only reason that I can think of is that the init() method is not invoked. The documentation of #BeforeEach says
#BeforeEach is used to signal that the annotated method should be
executed before each #Test, #RepeatedTest, #ParameterizedTest,
#TestFactory, and #TestTemplate method in the current test class.
I also tried running the tests in eclipse and there they always pass without any errors.
I am using maven 3.5.3.
I declared JUnit Jupiter 5.1.0 as dependency in my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.dk</groupId>
<artifactId>spielwiese</artifactId>
<version>0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spielwiese</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<archive>
<manifest>
<mainClass>de.dk.spielwiese.Spielwiese</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<finalName>Spielwiese</finalName>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.dk</groupId>
<artifactId>util</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Why is my init() method not invoked?
In my case the problem was that the #Test annotation was taken from wrong import.
Originally it was imported from org.junit.Test.
Once I have switched it to org.junit.jupiter.api.Test the problem was resolved.
Wrong original code:
import org.junit.Test;
#BeforeEach
...some code
#Test
...some code
Correct fixed code:
import org.junit.jupiter.api.Test;
#BeforeEach
...some code
#Test
...some code
Your init() method is not invoked because you have not instructed Maven Surefire to use the JUnit Platform Surefire Provider.
Thus, surprisingly your test is not even being run with JUnit. Instead, it is being run with Maven Surefire's support for what they call POJO Tests.
Adding the following to your pom.xml should solve the problem.
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Nowadays it is not necessary to add provider to plugin. Just add junit-jupiter-engine to your dependencies (as written in official documentation https://maven.apache.org/surefire/maven-surefire-plugin/examples/junit-platform.html).
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
I Faced the same issue for my gradle project.
Noticed that, #Test annotation using wrong package (org.junit.Test) and the issue fixed after using correct package (org.junit.jupiter.api.Test)
There is junit-jupiter-api dependency missing
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
In my case the problem was that I overwrote a method annotated with #BeforeEach in a subclass of the test, so the super methode was not called.
In order for Maven to execute tests properly with #BeforeEach you have to have your project correctly configured via pom.xml
Your project's pom.xml must contain these parts:
dependencyManagement with Junit BOM
dependency with Junit Jupiter
plugin with Maven Surefire Plugin
This is documented officially here and the official project examples are here.
Here is a link to the example project's pom.xml.
Here is the example project's pom.xml for your convenience:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>junit5-jupiter-starter-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.7.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
</project>
Sam Brannen's answer worked for me, but it seems that it doesn't work with the 2.22.0 version of maven-surefire-plugin unless you upgrade the junit-platform-surefire-provider to 1.2.0. Be aware!

NoClassDefFoundError after importing hikaricp through Maven dependency

I am getting a java.lang.NoClassDefFoundError: com/zaxxer/hikari/HikariDataSource error when launching my Java plugin on spigot. from what I can tell I have correctly imported it.
I know this question has been posted multiple times but by looking through 3-4 I do not see any clear answer to what is wrong.
The code crashes at hikari = new HikariDataSource() which is also the first hikari statement used.
My Pom
<groupId>drhampust.github.io</groupId>
<artifactId>Blank</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshot/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
it seems like hikari does not compile into jar but I can use its assets whilst coding.
Code:
import com.zaxxer.hikari.HikariDataSource;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.sql.*;
public class Main extends JavaPlugin {
//DataBase vars.
public String username, password, database, host, properties, table; //db variables
public int port; //db variable
//Connection vars
private HikariDataSource hikari;
#Override
public void onEnable() {
getLogger().info("onEnable is called!");
loadConfig();
new BukkitRunnable(){
#Override
public void run(){
connectToDatabase();
}
}.runTaskAsynchronously(this);
this.getServer().getPluginManager().registerEvents(new SetterGetter(), this);
}
#Override
public void onDisable() {
getLogger().info("onDisable is called!");
}
public synchronized void connectToDatabase() {
//Database details
String address = getConfig().getString("Database.address");
String name = getConfig().getString("Database.Name");
String username = getConfig().getString("Database.username");
String password = getConfig().getString("Database.password");
int port = getConfig().getInt("Database.port");
//Initialise hikari instace
hikari = new HikariDataSource();
//Setting Hikari properties
hikari.setMaximumPoolSize(10);
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
hikari.addDataSourceProperty("serverName", address);
hikari.addDataSourceProperty("port", port);
hikari.addDataSourceProperty("databaseName", name);
hikari.addDataSourceProperty("user", username);
hikari.addDataSourceProperty("password", password);
}
public void loadConfig() {
getConfig().options().copyDefaults(true);
saveConfig();
}
}
full crash report in a paste bin to make it easier to see:
https://pastebin.com/JEMz0f6T
My attempt to create a standalone program using hikaricp:
Code:
package test;
import com.zaxxer.hikari.HikariDataSource;
public class Main
{
public static void main(String[] args) {
HikariDataSource hikari = new HikariDataSource();
//Setting Hikari properties
hikari.setMaximumPoolSize(10);
hikari.setDriverClassName("com.mysql.jdbc.Driver");
hikari.setJdbcUrl("jdbc:mysql://" + "localhost" + ":" + "3306" + "/" + "plugin");
hikari.setUsername("Server1");
hikari.setPassword("227VU07dickCQjav");
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Test</groupId>
<artifactId>Test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>test.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
stacktrace: https://pastebin.com/fNQ7EFnQ
I hav posted an issue on the Hikaricp Github, it might not fit on there as it seems to be a problem only for me, but hey! maybe he can help.
I do not know why this is happening, i suspect that other people can complie HikariCP just fine, the question is why dosen't it work for me...
Edit: it seems like something similar has happend before:
https://www.spigotmc.org/threads/hikaricp-with-spigot-not-importing-with-the-jar.246851/ Checking if I can get my problem to fix itself using this information.
Okay By adding the new arguments to my pom.xml i have now removed the
NoClassDefFoundError and have now gotten this: https://pastebin.com/9DU9Tqra
But hey its a warning not a crash dump. meaning that it worked yay!
Missing details? Ask and I will see what i can do.
#Hampus, I have tried and check that in the version 3.4.0 of Hicari Pool, the class com.zaxxer.hikari.HikariDataSource is available in the package com/zaxxer/hikari. You can see the screenshot below. What I doubt is the repository you have added. Please remove the following from pom.xml and try.
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshot/</url>
</repository>
</repositories>
I know that you may be using your your nexus, this jar file is available in maven central. I provide below the mvn repository link for this.
https://mvnrepository.com/artifact/com.zaxxer/HikariCP/3.4.0
Problem is NoClassDefFoundError.
What fixed it? I fixed it following a post on spigotmc:
https://www.spigotmc.org/threads/hikaricp-with-spigot-not-importing-with-the-jar.246851/
and added:
<build>
<finalName>${project.name}</finalName>
<defaultGoal>clean package</defaultGoal>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</plugin>
</plugins>
</build>
to my pom.xml after adding it I used "clean" then "package" using maven and tried it and it worked. however i do get a warning:
[23:02:45] [Craft Scheduler Thread - 0/WARN]: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
[23:02:45] [Craft Scheduler Thread - 0/WARN]: SLF4J: Defaulting to no-operation (NOP) logger implementation
[23:02:45] [Craft Scheduler Thread - 0/WARN]: SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
However this is beside the original question.
I will select this as the answer unless someone finds a better solution.

AspectJ 1.9.4 with OpenJDK 11 Without Spring Context not working as a dependent module

I am trying to create custom loadtime annotations with AspectJ, Open JDK11 without Spring Context. It works fine within a module and annotations are weaving at class load time and aspects are executing at runtime. No issues, But when aspectJ implemented module added as a dependency on another module. AspectJ and annotations are not processing. Am I missing any configuration?
module-a
#Documented
#Inherited
#Target(METHOD)
#Retention(RUNTIME)
public #interface Counter {
String name() default "";
}
#Aspect
public class CounterAspect {
#Around("execution(* *.*(..)) && #annotation(counter)")
public void myBeforeLogger(ProceedingJoinPoint joinPoint, Counter counter) {
System.out.println("Okay - we're in the before handler...");
System.out.println("The test annotation value is: " + counter.name().toString());
}
resources/META-INF/aop.xml
<aspectj>
<aspects>
<aspect name="CounterAspect"/>
</aspects>
<weaver options="-verbose">
<!-- weave anything -->
<include within="*" />
</weaver>
</aspectj>
pom.xml
<properties>
<aspectj.version>1.9.4</aspectj.version>
</properties>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<argLine>
-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
module-b
pom.xml
<dependency>
<groupId>org.mymodule</groupId>
<artifactId>module-a</artifactId>
<version>1.0.0</version>
</dependency>
public class MyCounter {
#Counter(name="call_count")
public void count() {}
}
public class MyCounterTest {
#Test
public void testCount() {
MyCounter counter = new MyCounter();
counter.count();
//NOTE: I expect CounterAspect from module-a should be intercepted. It is not working!!!! There is no aspectJ class loading verbose in console.
}
}
I suggest you create a parent POM with some predefined properties, dependency versions and plugin configurations. Your two sub-modules (one for application + test, one for aspect) can use these definitions, which leads to shorter sub-module POMs:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.scrum-master</groupId>
<artifactId>aspectj-ltw-test-multi-module</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.source-target.version>11</java.source-target.version>
<aspectj.version>1.9.4</aspectj.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<!-- IMPORTANT -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>com.nickwongdev</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.12.1</version>
<configuration>
<!--<showWeaveInfo>true</showWeaveInfo>-->
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<Xlint>ignore</Xlint>
<complianceLevel>${java.source-target.version}</complianceLevel>
<encoding>${project.build.sourceEncoding}</encoding>
<!--<verbose>true</verbose>-->
<!--<warn>constructorName,packageDefaultMethod,deprecation,maskedCatchBlocks,unusedLocals,unusedArguments,unusedImport</warn>-->
</configuration>
<executions>
<execution>
<!-- IMPORTANT -->
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>de.scrum-master</groupId>
<artifactId>aspect</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>aspect</module>
<module>application</module>
</modules>
</project>
Please note that I am not using the original AspectJ Maven plugin but a fork which supports Java 11. The original still lags behind. As you said you want to use Java 11, you have to do that. With Java 8 you can use the original plugin.
Aspect module:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.scrum-master</groupId>
<artifactId>aspectj-ltw-test-multi-module</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>de.scrum-master</groupId>
<artifactId>aspect</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>com.nickwongdev</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
</dependencies>
</project>
<aspectj>
<aspects>
<aspect name="de.scrum_master.aspect.CounterAspect"/>
</aspects>
<weaver options="-verbose">
<!-- weave anything -->
<include within="*"/>
</weaver>
</aspectj>
package de.scrum_master.aspect;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
#Documented
#Inherited
#Target(METHOD)
#Retention(RUNTIME)
public #interface Counter {
String name() default "";
}
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class CounterAspect {
#Around("execution(* *.*(..)) && #annotation(counter)")
public void myBeforeLogger(ProceedingJoinPoint joinPoint, Counter counter) {
System.out.println(joinPoint + " -> " + counter.name());
}
}
Application module:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.scrum-master</groupId>
<artifactId>aspectj-ltw-test-multi-module</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>de.scrum-master</groupId>
<artifactId>application</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>de.scrum-master</groupId>
<artifactId>aspect</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
package de.scrum_master.app;
import de.scrum_master.aspect.Counter;
public class MyCounter {
#Counter(name = "call_count")
public void count() {}
}
package de.scrum_master.app;
import org.junit.Test;
public class MyCounterTest {
#Test
public void testCount() {
new MyCounter().count();
}
}
Now if you run mvn clean verify or just mvn clean test you will get the following console log for the application module test:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
[AppClassLoader#2aae9190] info AspectJ Weaver Version 1.9.4 built on Friday May 10, 2019 at 08:43:10 PDT
[AppClassLoader#2aae9190] info register classloader jdk.internal.loader.ClassLoaders$AppClassLoader#2aae9190
[AppClassLoader#2aae9190] info using configuration (...)/SO_AJ_LTWTestMultiModule_56397605/aspect/target/classes/META-INF/aop.xml
[AppClassLoader#2aae9190] info register aspect de.scrum_master.aspect.CounterAspect
[IsolatedClassLoader#74e52ef6] info AspectJ Weaver Version 1.9.4 built on Friday May 10, 2019 at 08:43:10 PDT
[IsolatedClassLoader#74e52ef6] info register classloader org.apache.maven.surefire.booter.IsolatedClassLoader#74e52ef6
[IsolatedClassLoader#74e52ef6] info using configuration (...)/SO_AJ_LTWTestMultiModule_56397605/aspect/target/classes/META-INF/aop.xml
[IsolatedClassLoader#74e52ef6] info register aspect de.scrum_master.aspect.CounterAspect
Running de.scrum_master.app.MyCounterTest
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access using Lookup on org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor (file:/(...)/.m2/repository/org/aspectj/aspectjweaver/1.9.4/aspectjweaver-1.9.4.jar) to class java.lang.ClassLoader
WARNING: Please consider reporting this to the maintainers of org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[AppClassLoader#2aae9190] info processing reweavable type de.scrum_master.aspect.CounterAspect: de\scrum_master\aspect\CounterAspect.aj
[AppClassLoader#2aae9190] info successfully verified type de.scrum_master.aspect.CounterAspect exists. Originates from de\scrum_master\aspect\CounterAspect.aj
execution(void de.scrum_master.app.MyCounter.count()) -> call_count
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.885 sec
Please especially note
execution(void de.scrum_master.app.MyCounter.count()) -> call_count
This is what you want, the load-time-woven aspect kicks in for your test.
Update: I created a GitHub repository for you. You can just clone it instead of copying all my code snippets from this answer.

JUnit 5 does not execute method annotated with BeforeEach

JUnit 5 does not invoke my method in a test class that is annotated with the #BeforeEach annotation, where I initialize some fields of the test object that are needed in the tests. When trying to access these fields inside a test method (method annotated with #Test) I obviously get a NullpointerException. So I added some output messages to the methods.
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TestClass {
private String s;
public TestClass() {
}
#BeforeEach
public void init() {
System.out.println("before");
s = "not null";
}
#Test
public void test0() {
System.out.println("testing");
assertEquals("not null", s.toString());
}
}
In the output of the tests when running mvn clean test I get the "testing" message from the test0() method annotated with #Test annotation, but the "before" message is not printed.
Running de.dk.spielwiese.TestClass
!!!testing!!!
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0 sec <<< FAILURE!
de.dk.spielwiese.TestClass.test0() Time elapsed: 0 sec <<< FAILURE!
java.lang.NullPointerException
at de.dk.spielwiese.TestClass.test0(TestClass.java:24)
The very obvious and only reason that I can think of is that the init() method is not invoked. The documentation of #BeforeEach says
#BeforeEach is used to signal that the annotated method should be
executed before each #Test, #RepeatedTest, #ParameterizedTest,
#TestFactory, and #TestTemplate method in the current test class.
I also tried running the tests in eclipse and there they always pass without any errors.
I am using maven 3.5.3.
I declared JUnit Jupiter 5.1.0 as dependency in my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.dk</groupId>
<artifactId>spielwiese</artifactId>
<version>0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spielwiese</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<archive>
<manifest>
<mainClass>de.dk.spielwiese.Spielwiese</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<finalName>Spielwiese</finalName>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.dk</groupId>
<artifactId>util</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Why is my init() method not invoked?
In my case the problem was that the #Test annotation was taken from wrong import.
Originally it was imported from org.junit.Test.
Once I have switched it to org.junit.jupiter.api.Test the problem was resolved.
Wrong original code:
import org.junit.Test;
#BeforeEach
...some code
#Test
...some code
Correct fixed code:
import org.junit.jupiter.api.Test;
#BeforeEach
...some code
#Test
...some code
Your init() method is not invoked because you have not instructed Maven Surefire to use the JUnit Platform Surefire Provider.
Thus, surprisingly your test is not even being run with JUnit. Instead, it is being run with Maven Surefire's support for what they call POJO Tests.
Adding the following to your pom.xml should solve the problem.
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Nowadays it is not necessary to add provider to plugin. Just add junit-jupiter-engine to your dependencies (as written in official documentation https://maven.apache.org/surefire/maven-surefire-plugin/examples/junit-platform.html).
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
I Faced the same issue for my gradle project.
Noticed that, #Test annotation using wrong package (org.junit.Test) and the issue fixed after using correct package (org.junit.jupiter.api.Test)
There is junit-jupiter-api dependency missing
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
In my case the problem was that I overwrote a method annotated with #BeforeEach in a subclass of the test, so the super methode was not called.
In order for Maven to execute tests properly with #BeforeEach you have to have your project correctly configured via pom.xml
Your project's pom.xml must contain these parts:
dependencyManagement with Junit BOM
dependency with Junit Jupiter
plugin with Maven Surefire Plugin
This is documented officially here and the official project examples are here.
Here is a link to the example project's pom.xml.
Here is the example project's pom.xml for your convenience:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>junit5-jupiter-starter-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.7.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
</project>
Sam Brannen's answer worked for me, but it seems that it doesn't work with the 2.22.0 version of maven-surefire-plugin unless you upgrade the junit-platform-surefire-provider to 1.2.0. Be aware!

Upgrading from BIRT 2.1.2; Platform.createFactoryObject() returns null

Management wants me to migrate a project that uses BIRT 2.1.2/Java 4/IBM WebSphere 5/Windows 2003 to Linux/Apache/Tomcat. I've chosen Tomcat 8, Java 8, and BIRT 4.5, to maximize the time before we again fall off the trailing edge.
I'm stuck on a failing test case that just initializes BIRT, with this code:
public static void init( String engineHome, String Birt_Resource_Path)
throws BirtException
{
if (!initialized) {
initialized = true;
DesignConfig config = new DesignConfig();
// config.setBIRTHome( engineHome);
Platform.startup( config);
IDesignEngineFactory factory =
(IDesignEngineFactory) Platform.createFactoryObject(
IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY);
if (factory == null) {
log.warn("Failed to construct DesignEngineFactory");
initialized = false;
} else {
birtEngine = factory.createDesignEngine(config);
birtResourcePath = Birt_Resource_Path;
}
log.info("DesignEngineService initialized! " + engineHome);
}
}
My test case calls this code, and later tests if the engine is initialized and fails then.
I read the notes about changes in BIRT 3.7 meaning I don't have to call config.setBIRTHome( engineHome), so I commented out that line.
The call to Platform.createFactoryObject(...) is still returning null, so I get the log message "Failed to construct DesignEngineFactory" and my test case fails.
I am using Eclipse Mars, and Maven for build and dependencies. My pom.xml is
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lxnx.sysman.webstar</groupId>
<artifactId>reportService</artifactId>
<packaging>war</packaging>
<version>2.0-DEVELOPMENT</version>
<name>Report Service</name>
<url>http://myproject.mycompany.com/ReportService</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<birt-version>4.5.0a</birt-version>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.birt.runtime</groupId>
<artifactId>org.eclipse.birt.runtime</artifactId>
<version>${birt-version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>opennms</groupId>
<artifactId>opennms-joesnmp</artifactId>
<version>20031201-173122</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>struts</groupId>
<artifactId>struts</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>com.mycompany.myproject</groupId>
<artifactId>ReportServiceImpl</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>c:\mycompany\app\myproject\bin\jars\sqljdbc42.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
<finalName>ReportService</finalName>
</build>
</project>
It looks like all the BIRT jars are in the Maven Dependencies library; at least org.eclipse.birt.runtime-4.5.0a.jar is there along with a hundred others.
What else do I need to do?

Categories

Resources