如何在测试类中为所有测试启动Jersey测试容器(Grizzly)一次?

时间:2016-07-22 10:54:10

标签: java junit jersey jersey-2.0 jersey-test-framework

我正在努力修复其中一个项目中的集成测试。目前,所有集成测试类都扩展了JerseyTest类。通过JerseyTest class我意识到它使用Junit的Before和After注释为每个测试方法启动和停止容器。

为什么这有必要?如果我们提起容器一次,运行测试并在结束时将其关闭,这还不够吗?

我们也使用Spring,上下文初始化需要时间。

在Junit4之前,我们通过使用布尔标志手动处理它来解决这个限制。

@Before
public void setup() {
  if(!containerStarted) {
   // start
   containerStarted = true;    
  }
 // else do nothing
}

2 个答案:

答案 0 :(得分:5)

您可以使用@BeforeClass和@AfterClass来覆盖JerseyTest的@Before和@After生命周期。这是代码模板:

public abstract class MyJerseyTest {
  private JerseyTest jerseyTest;
  public MyJerseyTest(){

  }

  @BeforeClass
  public void setUp() throws Exception {
    initJerseyTest() 
    jerseyTest.setUp();
  }

  @AfterClass
  public void tearDown() throws Exception {
    jerseyTest.tearDown();
  }

  private void initJerseyTest() {
    jerseyTest = new JerseyTest() {
      @Override
      protected Application configure() {
        // do somthing like
        enable(...);
        set(...);

        // create ResourceConfig instance
        ResourceConfig rc = new ResourceConfig();

        // do somthing like
        rc.property(...);
        rc.register(...);

        return rc;
      }
    };
  }
}

希望这有用。

答案 1 :(得分:2)

我们有类似的情况,使用jersey plus spring作为依赖注入框架(jersey-spring-bridge)。使用JerseyTest框架编写集成测试很棘手,因为它在测试之前启动容器并在测试之后停止容器。 这种方法可能有一个优点,但考虑到spring每次都会扫描和自动装配bean这一事实,它非常耗时且棘手。

  

如何初始化一个灰熊容器并将其用于   测试类中的所有测试?

为实现上述目标,我遵循以下步骤:

在测试类中作为实例变量,声明HttpServer的实例如下

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class OrderResourceTest {
    ...
    public static final String BASE_URI = "http://localhost:8989/";
    private static HttpServer server = null;
    ...
    ...
}

请注意,我不使用JerseyTest因为我想自己处理测试容器的启动/停止。现在,您需要使用@Before@AfterClass来设置服务器实例。 在@Before中,我们将设置server实例,以便在web.xml中加载我们的自定义过滤器/侦听器定义(例如以编程方式将web.xml加载到server实例中)< / p>

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

        WebappContext ctx = new WebappContext() {};
        ctx.addContextInitParameter("contextConfigLocation", "classpath:applicationContext.xml");

        ctx.addListener("com.package.something.AServletContextListener");

        server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
            ctx.deploy(server);
        }
    }

如果您注意到我正在使用@Before但是,if条件将使其作为@BeforeClass运行。不要完全记住为什么我没有使用@BeforeClass,我的猜测可能是由于if块中的一些配置。无论如何,如果你好奇,试一试。

  1. 使用将要测试的资源创建ResourceConfig,这包括您的资源/控制器,ExceptionMapper(如果有),任何其他应该加载的类。
  2. 创建一个WebappContext实例,然后以编程方式向其添加所有web.xml上下文init参数,例如applicationContextapplicationContext包含基于弹簧的配置。
  3. 如果您的web.xml中有监听器,则需要以编程方式添加它们,如上所示
  4. 如果您有任何过滤器或其他内容,则需要以编程方式将其添加到ctx
  5. 通过提供server
  6. 的URI和实例,使用Grizzly实例初始化ResourceConfig
  7. 您已经以编程方式创建了WebappContext,这只是web.xml,现在使用它的部署方法将服务器实例传递给它。这将运行WebappContext配置并将其部署到server实例。
  8. 现在你有一个测试运行Grizzly实例,你的web.xml加上应用于实例的特定于spring的配置。

    @AfterClass可能如下所示

    @AfterClass
        public static void tearDown() throws Exception {
            System.out.println("tearDown called ...");
            if (server != null && server.isStarted()) {
                System.out.println("Shutting down the initialized Grizzly instance");
                server.shutdownNow();
            }
        }
    

    使用REST保证框架的示例测试

    @Test
    public void testGetAllOrderrs() { 
        List<Orders> orders= (List<Orders>) 
        when().
            get("/orders").
        then().
            statusCode(200).
        extract().
            response().body().as(List.class);
    
        assertThat(orders.size()).isGreaterThan(0);
    }
    

    上述原因无需指定基本路径,因为我将REST保证的基本路径设置为

    RestAssured.baseURI = "http://localhost:8989/";
    

    如果您不想使用REST保证那么

    @Test
    public void testGetAllOrders() {
        Client client = ClientBuilder.newBuilder().newClient();
        WebTarget target = client.target(BASE_URI);
        Response response = target
                .path("/orders")
                .request(MediaType.APPLICATION_JSON)
                .get();
    
        assertThat(response.getStatus()).isEqualTo(200);
    
        JSONArray result = new JSONArray(response.readEntity(String.class));
    
        assertThat(result.length()).isGreaterThan(0);
    }
    

    基于泽西岛的进口

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