I have read many of the guides about working with Spring Boot and RESTful services, and many of them contain information about running unit tests, most notably "Building an Application with Spring Boot". However, I haven't seen anything that gives an example on how to unit test a Spring Boot application that consumes/depends on other Spring Boot applications, as is common in cloud micro-services architecture. So, for example, we have the following Spring Boot services:
ServiceMediator,
Adapter1,
Adapter2
ServiceMediator calls Adapter1 or Adapter2, depending on the input.
Is there a way to start up the Spring Boot services Adapter1 and Adapter2 before starting and testing the ServiceMediator in a Spring JUnit test?
The process-exec-maven-plugin could be helpful as allows to start multiple java processes at pre-integration-test phase (as standard Spring Boot apps), and it automatically takes care of shutting them down in the post-integration-test phase.
NOTE: The integration test should be run at the integration-test phase for that the maven-failsafe-plugin should be configured with spring-boot-maven-plugin see.
Then to run our integration tests verify or higher maven Lifecycle should be targeted, because the integration-test phase is in fact located between package and verify Lifecycles see Default Lifecycles.
The following maven (pom.xml) configuration worked for me:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.5.RELEASE</version>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<skip>${integration-tests.skip}</skip>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
<configuration>
<skip>${integration-tests.skip}</skip>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<skip>${integration-tests.skip}</skip>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.bazaarvoice.maven.plugins</groupId>
<artifactId>process-exec-maven-plugin</artifactId>
<version>0.7</version>
<executions>
<execution>
<id>switchboard-process</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<name>accounts-service</name>
<workingDir>/../../micro-service</workingDir>
<waitForInterrupt>false</waitForInterrupt>
<arguments>
<argument>java</argument>
<argument>-jar</argument>
<argument>${basedir}/../micro-service/target/micro-service-${project.version}-exec.jar</argument>
</arguments>
</configuration>
</execution>
<!--Stop all processes in reverse order-->
<execution>
<id>stop-all</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop-all</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Having an Integration Test class (WebServerIT) in test.java folder:
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = WebServerApp.class)
#WebIntegrationTest("server.port:0")
public class WebServerIT {
#Autowired
private WebApplicationContext webServerAppContext;
private MockMvc webServerMockMvc;
#Before
public void setUp() {
System.out.println("the test is set up");
webServerMockMvc = MockMvcBuilders.webAppContextSetup(webServerAppContext).build();
}
/**
* This test calls the WebServer's endpoint (/accounts/123456789) which in turn calls the micro-service rest api
* which is started using the process-exec-maven-plugin, otherwise the test would fail.
*/
#Test
public void testWebServerInteractionWithMicroService() throws Exception {
this.webServerMockMvc.perform(get("/accounts/123456789"))
.andExpect(status().isOk());
}
}
package controller;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.net.URL;
import mediator.CLPApplication;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = CLPApplication.class)
#WebAppConfiguration
#IntegrationTest()
public class ControllerTest {
#Value("${adapter.dependency.jar.location}")
private String adapterDependencyJarLocation;
#Value("${adapter.dependency.jar.name}")
private String adapterDependencyJarName;
#Value("${adapter.url}")
private String adapterURL;
#Value("${mediator.url}")
private String mediatorURL;
private URL mediator;
private URL adapter;
private RestTemplate template;
Process process = null;
#Before
public void setUp() throws Exception {
adapter = new URL(adapterURL);
template = new TestRestTemplate();
//
// Start the Atomic adapter
//
System.out.println(adapterDependencyJarLocation);
System.out.println("Starting Adapter");
try {
process = new ProcessBuilder("java", "-jar", adapterDependencyJarName)
.directory(new File(adapterDependencyJarLocation)).start();
// Try connecting 5 times with a 5 second pause between each
// to see if it started.
Thread.sleep(5000);
for(int i = 0; i <= 5; i++) {
try{
System.out.println("Testing to see if Adapter is up");
template.getForEntity(adapter.toString(), String.class);
System.out.println("Adapter Started");
break;
}
catch(RestClientException rce){
System.out.println("It's not up yet");
}
Thread.sleep(5000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Test
public void testMediator() throws Exception {
mediator = new URL(mediatorURL);
System.out.println("Calling Mediator");
ResponseEntity<String> response = template.getForEntity(mediator.toString(), String.class);
System.out.println(response.getBody());
// Getting back JSON, so check to see if it starts with an open bracket
assertThat(response.getBody(), Matchers.startsWith("{"));
}
#After
public void tearDown() {
if(process != null) {
process.destroy();
}
}
}
Related
I'm following the Spring training guide „Build a restful web service“ The application throws an error when I try and access http://localhost:8080/greeting. The error is:
ERROR 17903 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.util.FormatFlagsConversionMismatchException: Conversion = s, Flags = ] with root cause
Working on Ubuntu 20.04, openjdk version "11.0.14.1" 2022-02-08,
mvn -version:
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Java version: 1.8.0_312, vendor: Private Build, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Here are the relevant classes:
public class GreetingController {
private static final String template = "Hello, % s!";
private final AtomicLong counter = new AtomicLong();
public Greeting greeting(#RequestParam(value = "name",
defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I used Spring Initializr and added the dependency Spring Web as in the guide. Also the line:
com.example.demo.DemoApplication : Starting DemoApplication using Java 17.0.1
Seems like it is expecting Java 17 to run it. I have used Java 11 and Maven 2.6.7 in initializr and java 11 is set on my local machine.
Thanks in advance for any help
DataSperling
Solution: In the class:
public class GreetingController
The line:
private static final String template = "Hello, % s!";
Should read:
private static final String template = "Hello, %s!";
Also the url neads to be:
http://localhost:8080/greeting
NOT
https://localhost:8080/greeting
SSL is not required.
I have a simple poc project to check test suite functionality using Junit 5.
My pom.xml is:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
TestSuite.java class is
#Suite
#SuiteDisplayName("Sample Suite")
#SelectClasses({TestClassOne.class, TestClassTwo.class})
public class TestSuite {
#BeforeAll
public static void initMethod() {
System.out.println("Initiating tests from Suite");
}
#AfterAll
public static void tearDown() {
System.out.println("Completed Testing");
}
#Test
public void simpleTest() {
System.out.println("test method in suite");
}
}
Running the TestSuite either using mvn test or Run as Junit Test throws an exception
org.junit.platform.commons.JUnitException: TestEngine with ID 'junit-platform-suite' failed to discover tests
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:160)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverSafely(EngineDiscoveryOrchestrator.java:134)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:80)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:110)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:78)
What is wrong in my configuration/code? Any help/pointers to resolve this issue.
Thanks.
Happy New Year !!!
I have jOOQ (3.11.11) + H2 + Spring app, in which I am trying to run a simple JUnit test for persistence, but failing to do so with exceptions.
Here is my application.properties file:
spring.datasource.url=jdbc:h2:mem:jooq-test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
spring.datasource.platform=h2
spring.datasource.username = sa
spring.datasource.password =
And my test config class as:
#Configuration
public class DummyTestConfig {
#Bean
public DSLContext dsl() {
return DSL.using(SQLDialect.H2);
}
}
And my test case:
public class JooqRepositoryImplTest {
#MockBean
private PlatformCache platformCache;
#Autowired
private JooqRepositoryImpl JooqRepository;
private List<Entity> getDummyEntityList() {
List<Entity> data = new ArrayList<>();
for (int i = 0; i < 15; i++) {
data.add(getDummyEntity());
}
return data;
}
private Entity getDummyEntity() {
final Entity entity = new Entity();
entity.setCapacity(150);
return entity;
}
#Test
public void testDatabaseIsUp() {
assert(1 == JooqRepository.count());
}
#Test
public void testReplace() {
JooqRepository.getEntitiesByJDBC(124, "C", DirectionEnum.I, TrafficBucketEnum.D);
}
#Test
public void testSave() {
final List<Entity> data = getDummyEntityList();
JooqRepository.batchSaveByJDBC(data);
}
}
And my repository implementation:
#Repository
public class JooqRepositoryImpl implements CustomRepository {
#Autowired
private DSLContext dslContext;
public int count() {
return dslContext.fetchCount(MyTable.MY_TABLE);
}
#Transactional
#Override
public void batchSaveByJDBC(List<Entity> entities) {
dslContext.batchInsert(entities.parallelStream().map(convertEntityToRecord()).collect(Collectors.toList()));
}
private Function<Entity, Record> convertEntityToRecord() {
return entity -> {
final Record record = new Record();
record.setCapacity(entity.getCapacity());
return record;
};
}
#Override
public void batchReplaceByJDBC(List<Entity> entities) {
executeReplace(MyTable.MY_TABLE, entities.toArray());
}
public int executeReplace(Table<Record> table, Object[] values) {
return dslContext.execute("replace into {0} ({1}) values ({2})",
table,
dslContext.informationSchema(table).getColumns(),
DSL.list(Stream.of(values).map(DSL::val).collect(Collectors.toList()))
);
}
#Override
public void batchUpdateByJDBC(List<Entity> entities,
LegRoutingTO leg) {
dslContext.batchUpdate(entities.parallelStream().map(convertEntityToRecord()).collect(Collectors.toList()));
}
#Override
public void batchUpdateByJDBCPartial (
List<Entity> entities, LegRoutingTO leg) {
final Batch updates = dslContext.batch(
entities.parallelStream().map(convertEntityToRecord()).map(convertRecordToQuery()).collect(Collectors.toList()));
updates.execute();
}
private Function<Record, Query> convertRecordToQuery() {
return record -> {
final UpdateQuery<Record> query = dslContext.updateQuery(MyTable.MY_TABLE);
query.setRecord(record);
return query;
};
}
private Function<Record, Entity> convertRecordToEntity() {
return record -> {
final Entity entity = new Entity();
BeanUtils.copyProperties(record, entity);
return entity;
};
}
}
EDIT: My pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jooq</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<version>1.5</version>
<!-- Skip DB creation if the value of the skip.db.creation property is
true -->
<configuration>
<skip>${skip.db.creation}</skip>
</configuration>
<executions>
<!-- Execute SQL statements to the configured database -->
<execution>
<id>create-database-h2</id>
<phase>generate-sources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<!-- Configure the database connection -->
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/sampledb;INIT=CREATE SCHEMA IF NOT EXISTS
sampledb</url>
<username>sa</username>
<password></password>
<!-- Ensure that our changes are committed automatically -->
<autocommit>true</autocommit>
<!-- Configure the location of the invoked SQL script -->
<srcFiles>
<srcFile>src/main/resources/schema.sql</srcFile>
</srcFiles>
</configuration>
</execution>
</executions>
<dependencies>
<!-- Because we use the H2 database, we have to add it as the dependency
of this plugin. -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${com.h2database.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<version>3.4.4</version>
<executions>
<!-- Generate the required class from the database -->
<execution>
<id>generate-h2</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<!-- Because we use the H2 database, we have to add it as the dependency
of this plugin. -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${com.h2database.version}</version>
</dependency>
</dependencies>
<configuration>
<!-- Configure the database connection -->
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/sampledb;INIT=CREATE SCHEMA IF NOT EXISTS
FORECAST_MEASURES</url>
<user>sa</user>
<password></password>
</jdbc>
<generator>
<database>
<!-- Configure the used database dialect -->
<name>org.jooq.util.h2.H2Database</name>
<!-- Include all tables found from the PUBLIC schema -->
<includes>.*</includes>
<excludes></excludes>
<inputSchema>PUBLIC</inputSchema>
</database>
<!-- Generate classes for tables and records -->
<generate>
<records>true</records>
</generate>
<!-- Configure the target package and dirmectory -->
<target>
<packageName>com.xxxx.entity.jooq</packageName>
<directory>src/main/java</directory>
</target>
</generator>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.codehaus.mojo
</groupId>
<artifactId>
sql-maven-plugin
</artifactId>
<versionRange>
[1.5,)
</versionRange>
<goals>
<goal>execute</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
----------
When I try to run test cases, one of them passes (testBatchInsert) and the other two fail with following stacktrace:
org.jooq.exception.DetachedException: Cannot execute query. No Connection configured
at org.jooq_3.11.11.H2.debug(Unknown Source)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:319)
at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:393)
at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:380)
at org.jooq.impl.AbstractResultQuery.fetchStream(AbstractResultQuery.java:351)
at org.jooq.impl.SelectImpl.fetchStream(SelectImpl.java:2716)
at com.xxxx.repository.implementation.JooqRepositoryImpl.getEntitiesByJDBC(JooqRepositoryImpl.java:159)
at com.xxxx.repository.implementation.JooqRepositoryImpl$$FastClassBySpringCGLIB$$8ff9f08.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
at com.xxxx.repository.implementation.JooqRepositoryImpl$$EnhancerBySpringCGLIB$$923a185d.getEntitiesByJDBC(<generated>)
at com.xxxx.repository.implementation.JooqRepositoryImplTest.testReplace(JooqRepositoryImplTest.java:126)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:66)
The reason is your DSLContext configuration:
#Configuration
public class DummyTestConfig {
#Bean
public DSLContext dsl() {
return DSL.using(SQLDialect.H2);
}
}
It is not connected to your data source. Either, you need to inject your data source to this configuration and use that:
#Configuration
public class DummyTestConfig {
#Autowired
DataSource ds;
#Bean
public DSLContext dsl() {
return DSL.using(ds, SQLDialect.H2);
}
}
Or you don't do this at all and use the DSLContext that is injected by Spring boot. Add this to your application.properties file:
#jOOQ Configuration
spring.jooq.sql-dialect=H2
You can find an example project here: https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-spring-boot-example
I have this rule, which applies to all my tests:
protected String testName = "";
#Rule
public TestWatcher watcher = new TestWatcher() {
public void starting(Description description) {
testName = description.getMethodName();
}
};
It gets executed when I launch my tests with vanilla JUnit. However, when I launch my tests with Surefire (with Maven Surefire Plugin), it is not executed --> testName remains an empty string.
Here is the part of my POM when I declare Maven Surefire Plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<argLine>javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
<properties>
<property>
<name>listener</name>
<value>ru.yandex.qatools.allure.junit.AllureRunListener</value>
</property>
</properties>
<parallel>classes</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
<threadCount>80</threadCount>
<perCoreThreadCount>true</perCoreThreadCount>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
</dependencies>
</plugin>
How can I solve this problem?
Thanks in advance.
I have a mavenized build (maven3) which has a module to load a mySQL database dump. This works fine under Windows, but not under Linux.
Running maven with the -X switch, it generates the following output:
[DEBUG] Using mysql at /usr/bin/mysql
[DEBUG] Command to execute: mysql -uMYUSER --password=**** -hlocalhost --quick --max_allowed_packet=16M --default-character-set=utf8 -e "source /this/path/to/my/database/dump/is/longer/than/70/characters/the_dump.sql"
[ERROR] ERROR 1102 (42000): Incorrect database name '/this/path/to/my/database/dump/is/longer/than/70/characters/the_dump.'
If I run the debug output on the commandline directly, the the_dump.sql script works fine. My guess is that Maven is not recognizing the parameters correctly, and/or truncating them (note that the second parameter is truncated at 70 characters in the error message). I can't afford to have the build failing under Windows - due to certain commands in the database script, it can't run correctly by passing it into mysql with a "<" pipe.
Here is the relevant pom snippet:
<build>
<resources>
<resource>
<directory>META-INF</directory>
<targetPath>META-INF</targetPath>
</resource>
<resource>
<directory>${dumps.target.dir}</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>my.maven.plugin</groupId>
<artifactId>db-dumps-maven-plugin</artifactId>
<configuration>
<databasesToDump>${db.schemas.to.dump}</databasesToDump>
<documentStoreFolder>${documentstore.location}</documentStoreFolder>
<outputDirectory>${project.build.directory}/../${dumps.target.dir}</outputDirectory>
</configuration>
<executions>
<execution>
<id>dump-database</id>
<phase>prepare-package</phase>
<goals>
<goal>dump-db</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>build</id>
<build>
<plugins>
<plugin>
<groupId>my.maven.plugin</groupId>
<artifactId>db-dumps-maven-plugin</artifactId>
<executions>
<execution>
<id>create-database</id>
<phase>initialize</phase>
<goals>
<goal>create-db</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
And the execute snippet from the db-dumps-maven-plugin:
#Override
public void execute() throws MojoExecutionException {
final Set<String> dumpsToInsertLowerCase = evaluateDumpsToInsert();
final List<File> sqlFiles = findFiles(folderWithDumps, ".sql", dumpsToInsertLowerCase);
getLog().info("Inserting dumps: " + sqlFiles);
for (final File sqlFile : sqlFiles) {
String createCommand = "mysql -u%s --password=%s -h%s --quick --max_allowed_packet=16M --default-character-set=utf8 -e \"source %s\"";
Object[] createArgs = {username, password, hostname, sqlFile.getAbsolutePath().replace("\\", "/")};
executeCommand(createCommand, createArgs);
}
}
public void executeCommand(final String command, final Object[] arguments) {
final String commandToExecute = String.format(command, arguments);
mavenPlugin.getLog().debug("Command to execute: " + commandToExecute);
try {
final Process child = Runtime.getRuntime().exec(commandToExecute);
final InputStream inputStream = child.getInputStream();
readAndCloseStream(inputStream, false);
final InputStream errorStream = child.getErrorStream();
readAndCloseStream(errorStream, true);
// prevent leaking file descriptors, close stream
try {
child.getOutputStream().close();
} catch (final IOException ioe) {
mavenPlugin.getLog().warn("Unable to close stream. " + ioe);
}
// check return value
// 0 means a normal program termination
final int exitValue = child.exitValue();
if (exitValue != 0) {
throw new RuntimeException("Executing command failed. Exit code: " + exitValue);
}
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
Any idea why this happens, and how to make maven correctly interpret the source command?