jersey icon indicating copy to clipboard operation
jersey copied to clipboard

JerseyTest is not compatible with JUnit 5

Open OmarElabd opened this issue 8 years ago • 3 comments

When using JerseyTest with JUnit 5 a null pointer exception gets thrown:

java.lang.NullPointerException
	at org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:564)
	at org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:578)

The issue seems to be that the setup() and tearDown() functions in the JerseyTest class are not called in JUnit 5 as they would be in JUnit 4. JUnit 5 uses the convention of @Before and @After annotations.

Here is my workaround, in the test class that extends JerseyTest add the following two methods:

// do not name this setup()
@BeforeAll
public void before() throws Exception {
    super.setUp();
}

// do not name this tearDown()
@AfterAll
public void after() throws Exception {
    super.tearDown();
}

OmarElabd avatar Sep 06 '17 18:09 OmarElabd

Hey, I created a JUnit 5 extension for using the JerseyTest framework if you'd like to check it out: https://github.com/hanleyt/jersey-junit

Let me know if you guys would be interested in integrating this development.

Thanks, Tomás

hanleyt avatar Mar 04 '18 11:03 hanleyt

There is no need to worry. JUnit 5 ensures "Vintage" compatibility.

You juste have to import the JUnit 5 Vintage package:

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>${junit.jupiter.version}</version>
    <scope>test</scope>
</dependency>

Then, in your Jersey Test framework, just use JUnit 4 helpers:

package com.example.api.http;

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;

// JUnit 4 Test helper
import org.junit.Test;

import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;

// JUnit 5 Assertions (!!!)
import static org.junit.jupiter.api.Assertions.assertEquals;

public class UsersResourceTest extends JerseyTest {
    @Override
    protected Application configure() {
        return new ResourceConfig()
            .register(UsersResource.class)
            .register(JacksonFeature.class);
    }

    @Test
    public void testGet() {
        Response response = target().path("users/1").request().get(Response.class);

        assertEquals(200, response.getStatus());
        assertEquals("{\"data\":{}}", response.readEntity(String.class));
    }
}

Note, you can use both JUnit 4 and 5 in the same test. Quite cool isn't.

ValentinTrinque avatar Mar 09 '18 15:03 ValentinTrinque

Thanks for the suggestion @ValentinTrinque. Indeed, it's very nice that JUnit 5 has backward compatability.

However it doesn't solve the issue. Yes, junit vintage allows you to run JUnit 4 tests on the JUnit 5 platform. And yes, you can use any assertion library you want (Truth, AssertJ, Junit4 or 5 etc). These aren't tied to any junit version/platform, they all just throw some sort of AssertionFailed exception when a condition isn't met.

However by continuing to use the JUnit 4 test API you lose out on the all the other nice JUnit 5 features, in particular the new extension model that allows multiple extensions to be applied, and for dependencies to be injected into methods/constructors. ( plus many other features)

Extending a class to get features isn't a great way to do things as of course you can only extend one class so inheritance should be avoided where possible.

hanleyt avatar Mar 11 '18 19:03 hanleyt