Maven surefire tests failing in Spring framework project - spring

Maven is unable to successfully run my JUnit tests though they are being run without any problem on my Eclipse. I'm unable to solve it from the debug messages.
It is probably something to do with the Spring config because my other JUnit tests not relying on Spring are working fine.
Adding the surefire plugin forkMode as Always didn't work either.
Maven output
mvn install ... ... [INFO] --- maven-surefire-plugin:2.10:test (default-test) # AppServer --- [INFO] Surefire report directory:
C:..\surefire-reports
Running com.ws.impl.BrowserServiceImplTest Tests run: 2, Failures: 2,
Errors: 0, Skipped: 0, Time elapsed: 0.016 sec <<< FAILURE!
Failed tests: com.ws.impl.BrowserServiceImplTest.testGetStatuses()
com.ws.impl.BrowserServiceImplTest.testGetSellers()
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:test-context.xml")
public class BrowserServiceImplTest {
#Autowired
private BrowserServiceImpl browserServiceImpl;
#Test
public void testGetStatuses() {
// test code
}
// more code
}
Surefire report
<failure type="java.lang.NullPointerException">java.lang.NullPointerException
at com.ws.impl.BrowserServiceImplTest.testGetStatuses(BrowserServiceImplTest.java:48)
</failure>
Edit
Lines 48-49
List<String> statuses = browserServiceImpl.getStatuses();
assertEquals(12, statuses.size());
Edit 2
test-context.xml
<bean id="browserSvc" class="com.ws.impl.BrowserServiceImpl">
<property name="filterOptionsService" ref="filterOptionsService" />
</bean>
BrowserServiceImpl.java
#WebService(targetNamespace = "http://abc.def.com", portName = "BrowserPort", serviceName = "BrowserService")
public class BrowserServiceImpl implements BrowserService {
private FilterOptionsService filterOptionsService;
// more code
}

Related

How can I get my Maven/Mockito mock MVC test to print out a more detailed stack trace?

I'm using JUnit 5 and the spring-boot-starter-test (v 1.5) for Maven. I would want to test a controller method using mock MVC ...
#ExtendWith(MockitoExtension.class)
public class MyControllerTest {
...
MockMvc mockMvc;
...
#BeforeEach
public void setup() throws Exception {
...
mockMvc =
MockMvcBuilders.standaloneSetup(controller)
.setControllerAdvice(new RestResponseEntityExceptionHandler())
.build();
}
void testGetMethod() throws Exception {
... mocking ...
mockMvc
.perform(get("/mypath").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
Is there a way to get a more verbose stack trace when the test fails? When I run the test and there is a NullPointerException within the controller, the stack trace only prints the line where the unit test was failing
> mvn clean test -Dtest=MyControllerTest
...
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.676 s <<< FAILURE! - in com.rmyco.feature.controller.MyControllerTest
[ERROR] com.rmyco.feature.controller.MyControllerTest.testGetMethod Time elapsed: 1.663 s <<< ERROR!
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
at com.rmyco.feature.controller.MyControllerTest.testGetMethod(MyControllerTest.java:103)
Caused by: java.lang.NullPointerException
at com.rmyco.feature.controller.MyControllerTest.testGetMethod(MyControllerTest.java:103)
[INFO]
[INFO] Results:
[INFO]
[ERROR] Errors:
[ERROR] MyControllerTest.testGetMethod:103 ยป NestedServlet
I would like to know the exact line in the controller where things were blowing up.

cannot get docker image while using TestContainer

I am having a junit test written using test container (https://www.testcontainers.org/). when I run my test I get the following stack trace.
com.github.dockerjava.api.exception.UnauthorizedException: Status 401: {"message":"Get https://registry-1.docker.io/v2/testcontainers/ryuk/manifests/0.3.1: unauthorized: incorrect username or password"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:239)
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
at java.lang.Thread.run(Thread.java:748)
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 6.797 sec <<< FAILURE! - in com.openmind.primecast.web.rest.MessageHistoryReportingResourceIntTest
com.openmind.primecast.web.rest.MessageHistoryReportingResourceIntTest Time elapsed: 6.796 sec <<< ERROR!
org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=docker.elastic.co/elasticsearch/elasticsearch:7.11.2, imagePullPolicy=DefaultPullPolicy())
at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1286)
at org.testcontainers.containers.GenericContainer.logger(GenericContainer.java:615)
at org.testcontainers.elasticsearch.ElasticsearchContainer.<init>(ElasticsearchContainer.java:73)
at com.openmind.primecast.web.rest.MessageHistoryReportingResourceIntTest.startElasticServer(MessageHistoryReportingResourceIntTest.java:132)
Caused by: com.github.dockerjava.api.exception.UnauthorizedException: Status 401: {"message":"Get https://registry-1.docker.io/v2/testcontainers/ryuk/manifests/0.3.1: unauthorized: incorrect username or password"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:239)
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
at java.lang.Thread.run(Thread.java:748)
2021-03-24 20:30:31.584 WARN --- [r1-nio-worker-1] io.netty.channel.DefaultChannelPipeline : An exception '{}' [enable DEBUG level for full stacktrace] was thrown by a user handler's exceptionCaught() method while handling the following exception:
This is the code in the my junit test . Basically its trying to download elastic search docker image with version 7.11.2 . However i am unable to do so and an error is thrown on the console when i run my junit test.
public class MessageHistoryReportingResourceIntTest extends AbstractCassandraTest {
/**
* Elasticsearch version which should be used for the Tests
*/
private static final String ELASTICSEARCH_VERSION = "7.11.2";
private static final DockerImageName ELASTICSEARCH_IMAGE = DockerImageName
.parse("docker.elastic.co/elasticsearch/elasticsearch").withTag(ELASTICSEARCH_VERSION);
#BeforeClass
public static void startElasticServer() throws Exception {
container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE);
container.start();
}
}
this is my docker version
-bash-4.2$ docker --version
Docker version 17.03.1-ce_omn3, build 9b1cd46
in the pom.xml i have added the library
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>
<version>1.15.2</version>
<scope>test</scope>
</dependency>
appreciate if you can help
thank you
Apparently in https://github.com/testcontainers/testcontainers-java/issues/5121#issuecomment-1102909375 they suggested the following:
docker login index.docker.io
which fix my problem

Spring Boot JUnit 5 test with #ExtendWith(MockitoExtension.class) not working - mocks are null, MockitoJUnitRunner is working

I just migrated my project from Spring Boot 2.1 to 2.3 and thus have now JUnit 5 (with vintage) in place (also including mockito-core and mockito-junit-jupiter of version 3.3.3).
While all JUnit 4 tests are working fine my first JUnit 5 tests is not working correctly:
#ExtendWith(MockitoExtension.class)
public class SomeTest {
#InjectMocks
private Some to;
#Mock
private SomeProperties properties;
#Test
public void applied() {
....
//properties is null -> NPE
when(properties.getSome()).thenReturn("some");
....
}
The mocks are not injected (NPE in when statement). If i switch to old JUnit 4 style #RunWith(MockitoJUnitRunner.class) all is working fine.
So probably the old runner or vintage runner is used?
How to fix this and get tests with "#ExtendWith" working? I thought i can migrate step by step - let new tests run with junit5 runner.
Ensure you use the correct import for the #Test annotation:
JUnit 4: org.junit.Test
JUnit 5: org.junit.jupiter.api.Test
If you use maven and expect that tests run during mvn install, then upgrading maven-surefire-plugin may help. With old maven-surefire-plugin, the tests would be ignored and mvn install produce output similar to below:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running pl.somecompany.foo.FirstTest
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec - in pl.somecompany.foo.FirstTest
Running pl.somecompany.foo.SecondTest
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec - in pl.somecompany.foo.SecondTest
Running pl.somecompany.foo.ThirdTest
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec - in pl.somecompany.foo.ThirdTest
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
Upgrade maven-surefire-plugin version in your pom.xml (use the latest compatible with your Java version):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M8</version>
</plugin>

How do you resolve dependencies across all modules in a maven plugin?

I'm writing a Maven plugin that gets the resolved dependencies. It works fine for a single module project/pom, but fails on multiple module projects.
Here's a code snippet
#Mojo(
name="scan",
aggregator = true,
defaultPhase = LifecyclePhase.COMPILE,
threadSafe = true,
requiresDependencyCollection = ResolutionScope.TEST,
requiresDependencyResolution = ResolutionScope.TEST,
requiresOnline = true
)
public class MyMojo extends AbstractMojo {
#Parameter(property = "project", required = true, readonly = true)
private MavenProject project;
#Parameter(property = "reactorProjects", required = true, readonly = true)
private List<MavenProject> reactorProjects;
#Override
public void execute() throws MojoExecutionException {
for(MavenProject p : reactorProjects) {
for(Artifact a : p.getArtifacts()) {
...consolidate artifacts
}
}
}
}
The above code will consolidate all the resolved dependencies across all the modules, but it includes some additional ones.
Here's a sample project to work with. Please download this github repo
From the modules-project main folder, please run
mvn dependency:tree -Dverbose -Dincludes=commons-logging
You should see an output like this
[INFO] ------------------------------------------------------------------------
[INFO] Building core 0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # core ---
[INFO] com.github:core:jar:0.1-SNAPSHOT
[INFO] \- axis:axis:jar:1.4:compile
[INFO] +- commons-logging:commons-logging:jar:1.0.4:runtime
[INFO] \- commons-discovery:commons-discovery:jar:0.2:runtime
[INFO] \- (commons-logging:commons-logging:jar:1.0.3:runtime - omitted for conflict with 1.0.4)
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building web 0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # web ---
[INFO] com.github:web:war:0.1-SNAPSHOT
[INFO] +- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] \- com.github:core:jar:0.1-SNAPSHOT:compile
[INFO] \- axis:axis:jar:1.4:compile
[INFO] +- (commons-logging:commons-logging:jar:1.0.4:runtime - omitted for conflict with 1.1.1)
[INFO] \- commons-discovery:commons-discovery:jar:0.2:runtime
[INFO] \- (commons-logging:commons-logging:jar:1.0.3:runtime - omitted for conflict with 1.1.1)
[INFO] ------------------------------------------------------------------------
Notice that the module/project core depends on commons-logging 1.0.4 and commons-logging 1.0.3, but 1.0.3 is omitted due to a conflict and 1.0.4 is resolved.
This means that if you were to build core on its own, you should only get commons-logging 1.0.4.
Notice that module/project web depends on conflicting versions of commons-logging as well but resolves to 1.1.1.
Now if you were to build the "entire project" (modules-project) with the "mvn package" command, you should see that modules-project/web/target/myweb/WEB-INF/lib contains all the resolved dependencies and it includes ONLY commons-logging 1.1.1.
Here's the problem with the code
In the above code, reactorProjects is instantiated with 3 MavenProject's: modules-project, core, and web.
For modules-project and web, it resolves and returns commons-logging 1.1.1. However, for the core project, it resolves and returns commons-logging 1.0.4.
I want my plugin code to know that commons-logging 1.1.1 is the dependency that the build will produce, and not commons-logging 1.0.4
Any thoughts?
You practically have all it takes in your question. The following plugin will print in the console output the artifacts of the WAR project in the reactor:
#Mojo(name = "foo", aggregator = true, requiresDependencyResolution = ResolutionScope.TEST)
public class MyMojo extends AbstractMojo {
#Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
#Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
#Parameter(property = "reactorProjects", required = true, readonly = true)
private List<MavenProject> reactorProjects;
public void execute() throws MojoExecutionException, MojoFailureException {
MavenProject packagedProject = getWarProject(reactorProjects);
for (Artifact artifact : packagedProject.getArtifacts()) {
getLog().info(artifact.toString());
}
}
private MavenProject getWarProject(List<MavenProject> list) throws MojoExecutionException {
for (MavenProject project : list) {
if ("war".equals(project.getPackaging())) {
return project;
}
}
throw new MojoExecutionException("No WAR project found in the reactor");
}
}
What this does is that it acquires all the projects in the reactor with the injected parameter reactorProjects. Then, it loops to find which one of those is the "war" by comparing their packaging. When it is found, getArtifacts() will return all the resolved artifacts for that project.
The magic that makes it work is the aggregator = true in the MOJO definition:
Flags this Mojo to run it in a multi module way, i.e. aggregate the build with the set of projects listed as modules.
When added to core POM
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>test</id>
<phase>compile</phase>
<goals>
<goal>foo</goal>
</goals>
</execution>
</executions>
</plugin>
and run with your example project, this prints in the console:
[INFO] commons-logging:commons-logging:jar:1.1.1:compile
[INFO] com.github:core:jar:0.1-SNAPSHOT:compile
[INFO] axis:axis:jar:1.4:compile
[INFO] org.apache.axis:axis-jaxrpc:jar:1.4:compile
[INFO] org.apache.axis:axis-saaj:jar:1.4:compile
[INFO] axis:axis-wsdl4j:jar:1.5.1:runtime
[INFO] commons-discovery:commons-discovery:jar:0.2:runtime
This is good enough. With that, we can go forward and, for example, compare the resolved artifacts by the current project being build and the packaged project. If we add a method
private void printConflictingArtifacts(Set<Artifact> packaged, Set<Artifact> current) {
for (Artifact a1 : current) {
for (Artifact a2 : packaged) {
if (a1.getGroupId().equals(a2.getGroupId()) &&
a1.getArtifactId().equals(a2.getArtifactId()) &&
!a1.getVersion().equals(a2.getVersion())) {
getLog().warn("Conflicting dependency: " + a2 + " will be packaged and found " + a1);
}
}
}
}
called with
printConflictingArtifacts(packagedProject.getArtifacts(), project.getArtifacts());
that compares the current artifacts with the artifacts of the packaged project, and only retain those with the same group/artifact id but different version, we can get in the console output with your example:
[WARNING] Conflicting dependency: commons-logging:commons-logging:jar:1.1.1:compile will be packaged and found commons-logging:commons-logging:jar:1.0.4:runtime
The above assumed that our final packaging module was a WAR module. We could make that more generic and let the user specify which one of the module is the target module (i.e. that will package the real delivery).
For that, we can add a parameter to our MOJO
#Parameter(property = "packagingArtifact")
private String packagingArtifact;
This parameter will be of the form groupId:artifactId and will represent the coordinates of the target module. We can then add a method getPackagingProject whose goal will be to return the MavenProject associated with those coordinates.
The configuration of the plugin inside core would be
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>test</id>
<phase>compile</phase>
<goals>
<goal>foo</goal>
</goals>
<configuration>
<packagingArtifact>com.github:web</packagingArtifact>
</configuration>
</execution>
</executions>
</plugin>
And the full MOJO would be:
#Mojo(name = "foo", aggregator = true, requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.COMPILE)
public class MyMojo extends AbstractMojo {
#Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
#Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
#Parameter(property = "reactorProjects", required = true, readonly = true)
private List<MavenProject> reactorProjects;
#Parameter(property = "packagingArtifact")
private String packagingArtifact;
public void execute() throws MojoExecutionException, MojoFailureException {
MavenProject packagedProject = getPackagingProject(reactorProjects, packagingArtifact);
printConflictingArtifacts(packagedProject.getArtifacts(), project.getArtifacts());
}
private void printConflictingArtifacts(Set<Artifact> packaged, Set<Artifact> current) {
for (Artifact a1 : current) {
for (Artifact a2 : packaged) {
if (a1.getGroupId().equals(a2.getGroupId()) && a1.getArtifactId().equals(a2.getArtifactId())
&& !a1.getVersion().equals(a2.getVersion())) {
getLog().warn("Conflicting dependency: " + a2 + " will be packaged and found " + a1);
}
}
}
}
private MavenProject getPackagingProject(List<MavenProject> list, String artifact) throws MojoExecutionException {
if (artifact == null) {
return getWarProject(list);
}
String[] tokens = artifact.split(":");
for (MavenProject project : list) {
if (project.getGroupId().equals(tokens[0]) && project.getArtifactId().equals(tokens[1])) {
return project;
}
}
throw new MojoExecutionException("No " + artifact + " project found in the reactor");
}
private MavenProject getWarProject(List<MavenProject> list) throws MojoExecutionException {
for (MavenProject project : list) {
if ("war".equals(project.getPackaging())) {
return project;
}
}
throw new MojoExecutionException("No WAR project found in the reactor");
}
}
This implements the idea of above: when the user has given a target module, we use it as reference. When this parameter is not present, we default to finding a WAR in the reactor.

Kotlin - running an integration test, error `fun main is already defined`

I have written an integration test for a Web application but I don't know how to run this test. Maven build fails with the following error when I execute mvn test
[INFO] Compiling Kotlin sources from [src/main/kotlin]
[INFO] Classpath: <...>
[INFO] Classes directory is <...>\target\classes
[INFO] Module name is demo
[ERROR] <...>\src\main\kotlin\demo\Application.kt: (9, 1) 'public fun main(args: kotlin.Array<kotlin.String>): kotlin.Unit' is already defined in demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
Here is my main class (Application.kt)
package demo
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
#SpringBootApplication
open class Application
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
Here is a part of my test class
package demo
import org.junit.runner.RunWith
import org.springframework.boot.test.SpringApplicationConfiguration
import org.springframework.boot.test.WebIntegrationTest
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import demo.Application
import demo.model.City
import demo.repository.CityRepository
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebIntegrationTest({"server.port=8080"})
class CityControllerTest {
#Autowired
private var cityRepository: CityRepository?
private val restTemplate: RestTemplate = TestRestTemplate()
// ...
}
There is no such error when I execute mvn clean test. So I suppose Kotlin is frightened of previously compiled classes. Though I am very unsure...
What is the right way to run an integration test?
It is a bug (https://youtrack.jetbrains.com/issue/KT-10051). Already fixed and the fix will be delivered very soon

Resources