Chonaso's Commentary

InternetやIT技術などについて知ったこと、試したこと、考えたことを書いていきます。

JerseyTestでHttpServletRequestを使いたい

Jerseyのテストフレームワークは小気味よく動くけどフィルタとかちょっと凝ったことしても通るんだろうか、と不安に思っていたらやっぱりテストが通りませんでした。

どうもHttpServletRequestなどServletエンジンに依存するオブジェクトが取れない(nullになる)ようです。

いろいろワークアラウンドはあるようですが、grizzlyを使うのが通常のテストでは便利そうなので以下を参考に実施してみました。

<dependency>
  <groupId>org.glassfish.jersey.containers</groupId>
  <artifactId>jersey-container-grizzly2-servlet</artifactId>
  <version>2.13</version>
  <scope>test</scope>
</dependency>
package test;

import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import javax.ws.rs.ProcessingException;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.spi.TestContainer;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.glassfish.jersey.grizzly2.servlet.GrizzlyWebContainerFactory;
import org.glassfish.grizzly.http.server.HttpServer;

public abstract class GrizzlyJerseyTest extends JerseyTest {

  /**
   * 標準だとHttpServletRequestやHttpServletResponseが取れないので
   * grizzlyで代用する
   */
  @Override
  protected TestContainerFactory getTestContainerFactory() throws TestContainerException {

    return new TestContainerFactory() {

      @Override
      public TestContainer create(URI baseUri, DeploymentContext arg1) {
        return createTestContainer(baseUri);
      }

      protected TestContainer createTestContainer(URI baseUri){
        return new TestContainer() {
          private HttpServer server;

          @Override
          public ClientConfig getClientConfig() {
            return null;
          }

          @Override
          public URI getBaseUri() {
            return baseUri;
          }

          @Override
          public void start() {
            try {
              this.server = GrizzlyWebContainerFactory.create(
                  baseUri, Collections.singletonMap("jersey.config.server.provider.packages", "対象パッケージ")
              );
              System.out.println("HTTPサーバ立てます");
            } catch (ProcessingException e) {
              throw new TestContainerException(e);
            } catch (IOException e) {
              throw new TestContainerException(e);
            }
          }

          @SuppressWarnings("deprecation")
          @Override
          public void stop() {
            this.server.stop();
            System.out.println("HTTPサーバ落とします");
          }

        };
      }
    };
  }

}

これをextendsすることでHttpServletRequestを使ったテストができるようになりました。 他のワークアラウンドとしては、モックを作ってバインドする、というのがあるようです。