JUnit + Maven + Eclipse: Why #BeforeClass does not work? - eclipse

I am using JUnit 4, Maven 2 and latest Eclipse. Problem is simple: I would like to perform some setup (connecting to a database) before my tests are executed.
I tried #BeforeClass in many different locations but Eclipse and Maven are ignoring this. Any help on accomplishing this initial setup?
Thanks!
public abstract class BaseTestCase extends TestCase {
#BeforeClass
public static void doBeforeClass() throws Exception {
System.out.println("No good #BeforeClass");
// DO THE DATABASE SETUP
}
}
Now the tests extending BaseTestCase:
public class LoginActionTest extends BaseTestCase {
#Test
public void testNothing() {
System.out.println("TEST HERE");
assertEquals(true, true);
}
}
Maven and Eclipse just ignore my #BeforeClass ??? Any other way to perform setup before tests?

Sergio, you were right about extending TestCase causing the problem. If you extend TestCase, JUnit treats your test class as an old (pre JUnit 4 class) and picks org.junit.internal.runners.JUnit38ClassRunner to run it. JUnit38ClassRunner does not know about #BeforeClass annotation. Check out source code of runnerForClass method of AllDefaultPossibilitiesBuilder and runnerForClass method of JUnit3Builder for more details.
Note: This problem is not related to Eclipse or Maven.

I suspect that you are running with JUnit 3. Try renaming your test to something which does not start with "test". If the test is no longer executing, you are using JUnit 3 (which assumes that test methods are methods which starts with "test").
Please post your Eclipse launch config.

I have similar problem and I fixed it by specifying surefile and junit versions explisitly:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
<configuration>
<parallel>methods</parallel>
<threadCount>10</threadCount>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
More info is here: http://maven.apache.org/plugins/maven-surefire-plugin/examples/junit.html
It seems junit 3.8.1 version is used transiently through maven-resources-plugin and plexus-container-default. You can print dependency tree by calling mvn dependency:tree. I think there's no other way to make surefire use junit 4.

Related

How to enable Eclipse auto-completion in application.yml for custom properties declared by #ConfigurationProperties?

I made a simple class with configuration properties for my spring-boot project. Everything work as a charm (spring-boot catches options) except the fact that Eclipse doesn't recognize new properties as valid options in application.yml and highlights them as unknown.
Here is the class:
#Component
#ConfigurationProperties(prefix="server")
public class ServerProperties {
private Integer delay;
private DataAdapter dataAdapter = new DataAdapter();
// setters and getters were cut out for the sake of readability
public static class DataAdapter {
private String baseUrl;
private String targetCode;
// setters and getters
}
}
Autocompletion does not work for those properties:
I added the dependency for Spring Boot Configuration Processor to pom.xml as recommended in Spring.io reference, but it does not work as supposed.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Tried to switch to application.properties but autocompletion still doesn't work.
Spring boot configuration processor works as an annotation processor during compilation time.
It's necessary to enable annotation processing for the Eclipse project and register the processor:
Go to Project / Properties menu
Open Java Compiler / Annotation Processing. Enable project specific settings and check "Enable annotation processing"
Open Java Compiler / Annotation Processing / Factory Path. Check "Enable project specific settings"
Click "Add variable" button, select "M2_REPO", click "Extend" and find org/springframework/boot/spring-boot-configuration-processor/x.x.x.RELEASE/spring-boot-configuration-processor-x.x.x.RELEASE.jar in the Maven repository, where x.x.x is version of your Spring Boot.
Apply changes
Recompile the project, or just touch and save the class with configuration properties to trigger partial recompilation.
I had the same problem and fixed it by adding this to my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

Maven test finds but not executes tests

I have some test-classes under the folder src/test/java (some of these having name ending by *Test). Each class has some methods annotated with #Test
Running these tests with JUnit (on Eclipse, right click on the class, then run as, the JUnit Test) I have no problems. But I want to run these tests using mvn test.
The problem is that I obtain always this:
It seems that mvn finds the tests, but it doesn't execute them. Why?
Furthermore, it seems that also classes having a name that doesn't end with *Test are considered by Maven.
This is part of my pom.xml:
And this is part of my effective pom:
You are using a very outdated version of JUnit.
In JUnit 3.x, tests did not use annotations; the method names had to start with test*.
In JUnit 4.x, test methods had to be annotated with #Test, which is what you apparently have.
In your pom, you need to upgrade JUnit:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

Maven Exec plugin, ClassLoader ClassNotFoundException

I've tried many suggestions on StackOverflow, and tested with many combinations of setup and pom.xml for 3 days, none of them works. Please help.
I started with a big project with a lot of dependencies, spring-boot, hibernate, etc. Then I create another small console project which import and use some classes from the big project. They are not parent and child project. All I do is add <dependency/> to the child project pom, like this.
P.S. the big project has a <parent/> spring-boot-starter-parent and use spring-boot-maven-plugin.
<dependency>
<groupId>myGroup</groupId>
<artifactId>bigProject</artifactId>
<version>1.0.1</version>
</dependency>
This works on Eclipse with m2e, I just use "Run as" java application and the small project works.
But I need to upload and run those project on my linux VM, which does not use GUI and Eclipse, only terminal.
Then after some reading, I try to use maven exec plugin to run the small project. My steps:
1. do mvn clean install on the big project, confirmed that it appears in my /.m2, local repository.
2. run mvn compile on small project
3. run mvn exec:java on small project
It fails on step 2, those import ... in the class of small project throw package xxx does not exist. maven fail with compilation error.
Then, I try to simplify the problem. I create two test projects with only 1 class, myLib and HelloWorld console application, then I add myLib dependency (pom). HelloWorld project to print a message from the class in myLib package. run step 1 to 3. It works.
public class App
{
public static void main( String[] args )
{
//SystemLog from big project, does not work
//SystemLog log = new SystemLog();
//log.setValue("test value");
//System.out.println(log.getValue());
//CustomMessage from myLib, works fine
CustomMessage cm = new CustomMessage();
cm.setTheMessage("custom message");
System.out.println(cm.getTheMessage() );
System.out.println(CustomMessage.defaultMsg);
}
}
pom.xml of small project
<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>dependOnOthers</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dependOnOthers</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>myLibrary</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com</groupId>
<artifactId>bigproject</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>test.dependOnOthers.App</mainClass>
<!-- <arguments> <argument>argument1</argument> </arguments> -->
<!-- <arguments> <argument>-classpath</argument> <argument>target/lib/bigproject-1.0.1.jar</argument>
</arguments> -->
</configuration>
</plugin>
</plugins>
</build>
</project>
Then I add a reference to big project, try to print a log message using HelloWorld, it pass step 2, mvn compile, but when I do step 3, mvn exec:java, java.lang.ClassLoader.loadClass() throw ClassNotFoundException on the line where I new an SystemLog() instance, the class defined in big project.
Summarize:
Goal: try to run a console application using Maven exec plugin, which has a dependency on another project, that is installed in local repo /.m2
The SystemLog class is a model class with hibernate annotations.
1. small project depend on big project, fail on mvn compile, package does not exist.
2. HelloWorld depend on myLib, works fine.
3. HelloWorld depend on big project, fail at runtime with ClassNotFoundException.
It's a little late but i ran in the same error, migrating a project from 1.5.3 to 2.1.4
I have found a solution for this problem.
Spring Boot has changed the jar structure in version 2.0.0+, so you don't need to specify your class as <mainClass>test.dependOnOthers.App</mainClass>, you need to point JarLauncher as main entry point.
When the plugin will execute the jar, java will call the main method JarLauncher and several code of spring will be called after that he reads the manifest and call the class definied in Start-Class:. in your case test.dependOnOthers.App.
<configuration>
<!-- Since version 2 of spring, the jar is packed in
another way and has his main method here, don't worry in the MANIFEST file is described which file to boot -->
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
The old strucutre of Spring 1.0, was the classical java way todo it, so the java classloader can load it without problems and refer to the class when it is in the classpath, with the version 2.0.0+, they copy user class files and dependency into BOOT-INF, so the java classloader cannot load it anymore, you need to use the Spring classloader to get the class instance.
I have a workaround and know what is causing the problem, but don't know all the details, hope that someone will comment on this, or elaborate the answer.
The thing that cause this problem is spring-boot-maven-plugin, which I use to run spring-boot embedded tomcat server, using mvn spring-boot:run. This plugin seems to change something on the .jar file, maybe the manifest?
The workaround is to remove this plugin, run mvn clean install, that .jar installed in local repository will work correctly. run mvn compile on the small project. Then add the plugin back to big project, run mvn spring-boot:run
I do not know what the plugin changes that result in a .jar with package not exist, does it changes package name?
My workaround is clumsy, if there is a way to choose to compile with or without spring-boot-maven-plugin by defining maven goal, so that I do not need to change the pom for different build (with/without plugin). That would be a better solution.

Why would mvn clean install and eclipse differ in junit tests they run?

I have differences between Junit tests when I run them inside Eclipse and when they are run by maven surefire pluging doing an mvn clean install from a terminal
On one project, when I right click on src/test/java in Eclipse,Junit tells me there are 137 tests run. Doing mvn clean install gives me only 119. On this one, it seems that case in test name might be a possible explanation some of tests do not start with lower case and this makes surefire ignore them but are there any other possible explanation?
On a second project, I have a more annoying problem : en entire test package is not run by mvn clean install. I have 2 packages under src/test/java : com.project and com.project.services. Test classes under com.projectare run correctly by surefire, not the ones under com.project.services.
The only specificity I can see is classes under com.project.services have several level of inheritance :
public class ActualTestsCasesA extends GenericTestSituationA {}
public class GenericTestSituationA extends ServicesAbstractTests {}
public abstract ServicesAbstractTests extends ProjectAbstractTests {}
ActualTestsCasesA, GenericTestSituationA and ServicesAbstractTests are all under com.project.services test package. ProjectAbstractTests stays in an other maven project.
Here is the dependency to surefire plugin in my pom.wml :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<forkMode>always</forkMode>
<encoding>${project.build.sourceEncoding}</encoding>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
</configuration>
</plugin>
As you already discovered, Surefire has a specific naming convention when running tests. You can, however, configure additional naminig conventions to match your own project's test filenames. This is helpful for legacy tests that may not have been adhering to the Maven standard, or for a large suite of test classes you would rather not refactor.
Check out the Surefire documentation for details: http://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html
In your case, you could configure Surefire to include test classes with additional patterns like so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<forkMode>always</forkMode>
<encoding>${project.build.sourceEncoding}</encoding>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<includes>
<include>**/*Tests*.*</include>
<include>**/*TestSituation*.*</include>
</includes>
</configuration>
</plugin>
Eclipse, however, isn't bound by such restrictions. Instead, it relies on the existence of the junit4 library to run tests, and allows jUnit itself to determine if a class is considered a runnable test or not. See the Eclipse Mars docs for a little more info.

Ignoring Maven/Scala unit test files

I am writing my unit test cases for a Java project using Scala (JUnit 4). I am running the tests using Maven.
I have written a src/test/scala/com.xxx.BaseTest class for the tests to provide some common functionality (#BeforeClass, etc.), but no actual #Test cases.
Whenever I run the tests using mvn on the command line, it insists on trying to look for tests in the BaseTest class, and gets an error because there are none present.
Other than using an #Ignore, is there any way to have Maven/Scala/Surefire not try to run the BaseTest class? Adding the #Ignore is not a big deal, but my test run shows one more test than I actually have with the label "Skipped: 1".
UPDATE: I found a solution. I renamed BaseTest to Base; Maven now ignores it. Is there any other way?
You can either rename the base test class not to have *Test ending, for example BaseTestCase.java. This is what I would recommend.
Most likely maven executes tests with surefire plugin, so alternatively you just can configure surefire plugin to skip BaseTest.java. I think, by default surefire assumes that all classes ending with *Test are test classes. Something like this in the pom.xml.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<excludes>
<exclude>**/BaseTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>