JerseyTestをJUnit5で実行する方法

fixing Jersey
スポンサーリンク

JerseyでREST APIを作成した時、JerseyTestがJUnit5で動かなくて困ったことがありました。

どうやら、JerseyTestはJUnit5との互換性がないようです。(2021/07/05時点)

でも、JerseyTestをJUnit5で実行したいんだよなぁ

ということで、この記事ではJerseyTestをJUnit5で実行する方法を紹介します。

今回は例として、こんな感じのサンプルプログラムを作成しました。

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;

@Path("example")
public class ExampleResource {

	@GET
	@Path("healthcheck")
	public Response helthCheck() {
		return Response.ok().build();
	}
}

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ExapmleResourceTest extends JerseyTest {
	
    @BeforeAll
    public void before() throws Exception {
        super.setUp();
    }

    @AfterAll
    public void after() throws Exception {
        super.tearDown();
    }

    @Override
    protected Application configure() {
        return new ResourceConfig(ExampleResource.class);
    }

    @Test
    public void test() {
        Response response = target("example/healthcheck").request().get();
        assertEquals(Status.OK.getStatusCode(), response.getStatus());
    }
}

<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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>simple-service</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>simple-service</name>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>
         <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
        </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-engine</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <inherited>true</inherited>
                <configuration>
                    <source>15</source>
                    <target>15</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>com.example.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <properties>
        <jersey.version>3.0.2</jersey.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.jupiter.version>5.7.1</junit.jupiter.version>
    </properties>
</project>

JerseyのTestをJUnit5で実行する手順

1. pom.xmlを書き換える

JUnit5とJUnit4では、pom.xmlの<dependencies>に記載する内容が異なります。


JUnit4で実行するとき

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>


JUnit5で実行するとき

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.7.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.7.1</version>
    <scope>test</scope>
</dependency>

JUnit5を動かすには、最低限junit-jupiter-apiとjunit-jupiter-engineがあればOKです。

また、Jersey Test Frameworkも<dependencies>に加えておきましょう。

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
</dependency>

2. importを書き換える

JUnit5では、新しいorg.junit.jupiterパッケージを使用します。importを書き換えましょう。


JUnit4

import org.junit.Test;


JUnit5

import org.junit.jupiter.api.Test;

3. 古いアノテーションとクラス名を書き換える

ポイントを抜き出して説明します。

@TestInstance(TestInstance.Lifecycle.PER_CLASS)、@Brefore→@BeforeAll、@After→@AfterAll

アノテーションを追加します。

@TestInstance(TestInstance.Lifecycle.PER_CLASS)

@TestInstance(TestInstance.Lifecycle.PER_CLASS)で、クラス単位でインスタンスを生成するように変更しています。この設定を加えることで、@BeforeAllと@AfterAllが使用できるようになります。

@Brefore → @BeforeAll

@After → @AfterAll

それに伴い、importも下記のものに更新します。

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;

Assertionsを使用

JUnit5では、org.junit.jupiter.api.Assertionsクラスのstaticメソッドとしてアサーションを使用します。こちらも書き換えておきましょう。

例では、このようにimportしています。

import static org.junit.jupiter.api.Assertions.assertEquals;

4. setUp()とtearDown()を呼び出すようにする

最後に一つ、注意点があります。

JUnit5でJerseyTestを実行するには、setUp()とtearDown()は明示的に呼び出す必要があります。

@BeforeAll
public void before() throws Exception {
    super.setUp();
}

@AfterAll
public void after() throws Exception {
    super.tearDown();
}


JUnit4では特にコーディングしなくても呼び出されていたのですが、JUnit5からは呼び出されないようになったみたいです。

setUp()とtearDown()を呼び出さないとNullPointerExceptionになります。

java.lang.NullPointerException: Cannot invoke "org.glassfish.jersey.test.spi.TestContainer.getBaseUri()" because the return value of "org.glassfish.jersey.test.JerseyTest.getTestContainer()" is null

setUp()とtearDown()は明示的に呼び出すように実装しましょう。

おわり

これで、JerseyTestがJUnit5で実行されるようになりました。

もしかしたら、今後のバージョンでsetUp()とtearDown()を呼び出さなくてもJUnit5で実行できるようになるかも。

期待しておきましょう。

コメント

タイトルとURLをコピーしました