How to define #Rule and #ClassRule with junit5 - junit5

I want to migrate junit4 to junit5 , And I use #Rule annotations for junit4. Like this:
public class A {
#ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
}
And I want migrate junit5 but I don't know how to change Rule and ClassRule
This is my pom.xml section junit5
<!--junit5-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
<!-- Only required to run tests in an IDE that bundles an older version -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.17.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
How to I use Rule and ClassRule at junit5?

JUnit Jupiter introduces a new extension mechanism. Instead of Rules, you have to use the new SpringExtension which is available in Spring 5. There's a backport for Spring 4 by the original author as well.

Since it looks like you're not using Spring already, you do not "have to use the new SpringExtension", you can just use the BeforeAllCallback and AfterAllCallback extension APIs in JUnit 5. There's an example at Baeldung, about 2/3 of the way down the page. Note that "TestExtensionContext" is now "ExtensionContext".

Related

How to migrate a RestConfigurationRule from serenity 1.5.11 to 2.6.0

I'm updating serenity version from 1.5.11 to 2.6.0 in order to be able to run tests with Junit 5, along with serenity-rest-assured dependency. How can I re write this rule below using 2.6.0? Looks like RestConfigurationRule is not present in 2.6.0
#Rule
public final RestConfigurationRule rule = new RestConfigurationRule(new TestConfiguration(),
new LogConfiguration(), new RelaxedHttpsConfiguration());
POM :
<properties>
<argLine/>
<serenity.version>2.6.0</serenity.version>
<serenity.cucumber.version>1.9.51</serenity.cucumber.version>
<jackson.version>2.12.1</jackson.version>
<junit.jupiter.version>5.7.0</junit.jupiter.version>
</properties>
<dependencies>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-core</artifactId>
<version>${serenity.version}</version>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-cucumber</artifactId>
<version>${serenity.cucumber.version}</version>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-rest-assured</artifactId>
<version>${serenity.version}</version>
</dependency>
<dependency>
<groupId>io.github.fabianlinz</groupId>
<artifactId>serenity-junit5</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
I don't think so.
RestConfigurationRule already exist in last version

Trying to test static method using powermock

I'm trying to do a test on a code which requires to mock some static methods. I found in the that using powermock, I will be able to mock the static methods being used.
I tried adding these dependencies power mock module-junit4 dependency as well as powermock-api-mockito and setting their versions explicitly to 1.7.1:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.1</version>
<scope>test</scope>
</dependency>
#RunWith(PowerMockRunner.class)
#PrepareForTest({SystemParameterQueryHelper.class})
public class VccTemplateConvertorTest{}
Exception in thread "main" java.lang.NoSuchMethodError: org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.getFrameworkReporterFactory()Lorg/powermock/core/reporter/MockingFrameworkReporterFactory;
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.getMockingFrameworkReporter(JUnit4TestSuiteChunkerImpl.java:140)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:119)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
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)
You are using a fairly dated version of PowerMock. Looking at the documentation:
PowerMock version 2.0.0 and upper has support of Mockito 2. PowerMock version 1.7.0 and upper has experimental support of Mockito 2.
In this case emphasis is on experimental.
I would suggest to try and update the PowerMock version you're using. This is my current configuration:
<properties>
...
<version.mockito>2.23.4</version.mockito>
<version.powermock>2.0.2</version.powermock>
</properties>
<dependencies>
...
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${version.mockito}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${version.powermock}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${version.powermock}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>${version.powermock}</version>
<scope>test</scope>
</dependency>
</dependencies>

Can't use #Value and #Autowired with properties in Spring Cloud Configuration Server

I have a SpringBoot 1.5.12 app using the Edgware.SR3 Spring Cloud release.
The following code:
#Configuration
public class HmlConfig
{
#Value("${jms.destination.name}")
...
}
...
#RestController
#RequestMapping("/api")
public class HmlRestController
{
#Autowired
private JmsTemplate jmsTemplate;
...
}
Raises the following exception:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jms.destination.name' in value "${jms.destination.name}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
Here is my bootstrap.yml content:
spring:
application:
name: hml-core
profiles:
active:
default
cloud:
config:
uri: http://localhost:8888/hml
Going to http://localhost:8888/hml/hml-core/default correctly displays the properties. Did I miss anything ?
Depending on your logs, your client can't access to the Config Server, this is why the field jms.destination.name can't be injected.
Add the full stacktrace of your client will be helpful
Do you happen to have spring.main.sources set somewhere?
We had the excact same issue and removing that line helped us. It seems that having this in the bootstrap.yml hinders the app to connect to cloud config server. This results in missing props.
Also having spring.main.sources param on config server side caused a server side exception. See Spring cloud config /refresh crashes when spring.main.sources is set
I'm updating this post with the results of the last tests. It appears that including the maven dependencies in each of the modules solves the issue and the configuration is then found as expected.
In my original design I had a parent POM which factorized all the spring boot dependencies, as shown below:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
This way the configuration client doesn't find the config server and the mentioned exception is raised. Modifying the parent POM such that to include only the dependencyManagement, as shown below:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
and moving the dependencies in the config server POM as follows:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
and in the config client as follows:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
completely solves the problem and everything works as expected. I don't have any explanation of this as including all the common dependencies in the parent POM should have exactly the same effect as including them in each individual module. In my opinion this shows some instabilities and strange behavior of Spring Boot and Spring Cloud. I don't have time to dig more and to try to understand what happens. Anyway, given this kind of issues, as well as the lack of any support including on this site, we moved from Spring.
But if someone has any explanation of this, I'm still interested to know.
Kind regards,
Nicolas

Can I make wso2 msf4j work with jersey?

WSO2 MSF4J to improve the size adds their own jaxrs-delegate which strips quite a bit of functionality from JAX-RS standard such as UriBuilder or BadRequestException
I've noted a few of the limitations of WSO2's MSF4J implementation https://github.com/wso2/msf4j/issues/290#issuecomment-329673266
So what I tried to do was see if I can replace the WSO2 jaxrs-delegate with Jersey instead. I excluded it from the core and tried to put in the jersey and jackson dependencies, but in the end it didn't work out.
I was wondering if this is even duable.
TL;DR
Set the BOMs (note don't use the latest versions as of the time of this writing)
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.8.10</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>2.26-b03</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Add the dependencies
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
Exclude the delegate from core
<dependency>
<groupId>org.wso2.msf4j</groupId>
<artifactId>msf4j-core</artifactId>
<version>2.1.0</version>
<exclusions>
<exclusion>
<groupId>org.wso2.msf4j</groupId>
<artifactId>jaxrs-delegates</artifactId>
</exclusion>
</exclusions>
</dependency>

MessageBodyWriter not found for media type=application/json even while Jackson is included

I've seen some solutions to this problem but it seems like following them doesn't solve my problem. I am returning a simple string array and when I return it, I am getting this error:
Severe: MessageBodyWriter not found for media type=application/json, type=class [Ljava.lang.String;, genericType=class [Ljava.lang.String;.
The method is really simple (gets a list of files)
#GET
#Produces(MediaType.APPLICATION_JSON)
public String[] getSegments(#PathParam("userId") String userId,
#PathParam("deviceId") String deviceId) {
System.out.println("in get, userId passed: " + userId);
String[] segments = storage.getSegments(userId, deviceId);
return segments;
}
My POM.XML seems to have all the things recommended in other posts:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>RoverServerLib</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-servlet-portability</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
The problem is with MOXy. It doesn't know how to handle String arrays. When you have MOXy on the classpath, it is the used as the default. To use Jackson (jersey-media-json-jackson). You just need to register the JacksonFeature. This will disable MOXy. Note that even just removing MOXy from your project, will have no affect, as Glassfish has it, so you need to make sure to register the JacksonFeature.
You should also get rid of jackson-jaxrs-json-provider. jersey-media-json-jackson already pulls it in (but a different version).
Another thing is that Glassfish already has it's own version of Jersey and friends. If you don't mark all your Jersey related dependencies as <scope>provided</scope>, then it's possible you may have version conflicts. So you should make them all provided. Glassfish 4.1 uses Jersey 2.10.4. If you need some newer version features, I would recommend updating Jersey in Glashfish.