0

依存性注入 (spring-jersey モジュール) に spring を使用し、オブジェクト リレーショナル マッピング (ORM) に hibernate を使用する jersey Web サービスがあります。以下の条件を考慮して統合テストを開発するため:

  1. テスト クラス全体に対して 1 回だけテスト コンテナーを初期化する
  2. カスタム リスナー、フィルター、サーブレットなどをテスト コンテナーに登録する
  3. @Context HttpServletRequest が null でないことを確認してください

このhttps://java.net/jira/browse/JERSEY-2412ジャージー プロジェクト JIRA タスクHttpServletRequestによると、これはタスクWorks as desginedの解像度に示されているとおりです。Grizzly コンテナーで統合テストを実行すると、httpサーバーで統合テストが実行されるため、 HttpServletRequest、HttpServletResponseなどのサーブレットベースの機能への依存は利用できません。

この問題に対処する方法に関する標準的な解決策はないようです。Jerseyコミュニティは、このhttps://java.net/jira/browse/JERSEY-2417 JIRA チケットに記載されているように、貢献者によって開発された機能に対して明らかにオープンです。この機能が実装されるまで、どのような回避策が考えられますか? 私の調査に基づいて、次のような投稿をいくつか見つけました。

  1. 外部コンテナーを使用する (私もしたくない場合はどうすればよいですか?)
  2. jersey の jetty モジュールを使用します (Jetty を使用したくない場合はどうすればよいですか?)
  3. このプロジェクトには適用されない SpringMVC 固有のソリューション (Spring MVC を使用しないため)

では、依存性注入に spring-jersey ブリッジを使用し、 サーブレットベースの機能に依存する jersey ベースの Web サーバーで統合テストを正常に実行するための最適なソリューションは何でしょうか?

4

1 に答える 1

0

これは Jersey の標準的な動作であり、HttpServletRequestなどのサーブレット ベースの機能を許可する機能はまだ利用できません。私の研究に基づいて、次の条件を達成できました

  1. テスト クラス全体に対して 1 回だけテスト コンテナーを初期化する
  2. カスタム リスナー、フィルター、サーブレットなどをテスト コンテナーに登録する
  3. @Context HttpServletRequest が null でないことを確認してください

grizzly コンテナーを手動で開始/停止し、カスタムの jersey ベースの WebappContext に grizzly コンテナー インスタンスをデプロイします。他の誰かがそのような問題に遭遇した場合の手順は次のとおりです

  1. HttpServer を作成する
  2. @Before で、 web.xmlを反映 するカスタムWebappContextを作成し、 WebappContextを使用して HttpServer インスタンスをデプロイします。
  3. 統合テスト中にHttpServletRequestなど のサーブレットベースの機能を使用できるようにするには、 ServletRegistrationを使用して、以下に示すようにサーブレット コンテナー内にアプリケーションをロードします。

ステップ1

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ResourceEndpointIntegrationTest{
    @Context
    private HttpServletRequest httpReq;

    private static Logger logger = Logger.getLogger(ResourceEndpointIntegrationTest.class);

    public static final String BASE_URI = "http://localhost:8989/";
    private static HttpServer server = null;

    @BeforeClass
    public static void initTest() {
        RestAssured.baseURI = "http://localhost:8989/";
    }
...
}

SpringJUnit4ClassRunner.classおよび@ContextConfigurationを使用して、テスト用のapplicationContext.xmlをロードします。また、 @Context HttpServletRequestを宣言し、後で使用するHttpServerのインスタンスを作成します。ここでは、Rest-Assured 固有の目的で@BeforeClassを使用します (使用する必要はありません)。オプションです。

ステップ2

@Before
    public void setup() throws Exception {
        if (server == null) {
            System.out.println("Initializing an instance of Grizzly Container ...");
            final ResourceConfig rc = new ResourceConfig(ResourceEndpointIntegrationTest.class, ..., ..., ...); //update

            WebappContext ctx = new WebappContext("IntegrationTestContext");
                        //register your listeners from web.xml in here
            ctx.addListener("com.xxx.yyy.XEndpointServletContextListener");
                        //register your applicationContext.xml here
            ctx.addContextInitParameter("contextConfigLocation", "classpath:applicationContext.xml");

                        //ServletRegistration is needed to load the ResourceConfig rc inside ServletContainer or you will have no 
                        //Servlet-based features available 
            ServletRegistration registration = ctx.addServlet("ServletContainer",
                    new ServletContainer(rc));

                        //Initialize the Grizzly server passing it base URL
            server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI));

                        //Deploy the server using our custom context
            ctx.deploy(server);
        }
    }

@Beforeセットアップはすべてのテストに対して実行されますが、if 条件により、セットアップメソッドが@BeforeClassのように動作するように強制され、テスト クラス全体から@BeforeClassの静的な性質を引いたものに対してサーバーを 1 回初期化することができます。

テストクラス内のすべてのテストに対してサーバーを一度初期化する理由は、そうしないと次のワークフローになるからです。

  1. サーバーが開始されました
  2. 春は豆のスキャンを開始します
  3. 春は自動配線されます
  4. Spring セットアップ sessionFactory など
  5. テストが実行されます
  6. 春は文脈を破壊する
  7. サーバーがシャットダウンされました
  8. テストごとに手順 1 から 7 を繰り返します

上記は非常に時間がかかり、技術的に実行できないため、コンテナーを一度初期化します (これが、テスト コンテナーの起動/シャットダウンを制御したいため、JerseyTestを拡張しない理由です)。

#ステップ 3

@AfterClass
    public static void tearDown() throws Exception {
        System.out.println("Integration tests completed. Tear down the server ...");
        if (server != null && server.isStarted()) {
            server.shutdownNow();
            System.out.println("Grizzly instance shutdown completed");
        }
    }

ステップ 3 では、@AfterClassを使用して、統合テストの目的で使用されるgrizzlyインスタンスをシャットダウンします。

サンプルテストは次のようになります

@Test
    public void testCreateSomethingReturnSuccessfully() {
        JSONObject something = new JSONObject();
        cust.put("name", "integrationTest");
        cust.put("age", 33);

        given().
            contentType(ContentType.JSON).
            body(something.toString()).post("/someEndpoint").
        then().
            statusCode(200).
        assertThat().
            body("id", greaterThan(0)).
            body("name", equalTo("integrationTest")).
            body("age", equalTo(33));
    }

(Gradle) 関連する依存関係の一部

compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.23.2'
compile group: 'org.glassfish.jersey.test-framework.providers', name:'jersey-test-framework-provider-grizzly2', version:'2.23.2'
compile group: 'org.springframework', name:'spring-test', version:'4.3.2.RELEASE'
compile group: 'io.rest-assured', name:'rest-assured', version:'3.0.1'


// Spring
    compile group: 'org.springframework', name: 'spring-core', version: '4.3.2.RELEASE'
    compile group: 'org.springframework', name: 'spring-beans', version: '4.3.2.RELEASE'
    compile group: 'org.springframework', name: 'spring-web', version: '4.3.2.RELEASE'
    compile group: 'org.springframework', name: 'spring-jdbc', version: '4.3.2.RELEASE'
    compile group: 'org.springframework', name: 'spring-orm', version: '4.3.2.RELEASE'

    // Jersey-Spring bridge
    compile (group: 'org.glassfish.jersey.ext', name: 'jersey-spring3', version: '2.23.2'){
        exclude group: 'org.springframework', module: 'spring-core'
        exclude group: 'org.springframework', module: 'spring-web'
        exclude group: 'org.springframework', module: 'spring-beans'
        exclude group: 'org.springframework', module: 'spring-jdbc'
        exclude group: 'org.springframework', module: 'spring-orm'
    }

輸入品の一部

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
于 2016-10-07T14:19:58.110 に答える