7

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

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

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

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

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

2 回答 2

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;
      }
    };
  }
}

希望这会有所帮助。

于 2016-08-03T03:32:17.403 回答
2

我们也遇到过类似的情况,使用 jersey 加 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实例中)

@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,这包括您的 Resource/Controller、ExceptionMapper(如果有)以及应加载的任何其他类。
  2. 创建 WebappContext 的实例,然后以编程方式将所有web.xml上下文初始化参数添加到其中applicationContext,例如。其中applicationContext包含基于弹簧的配置。
  3. 如果您的 web.xml 中有一个侦听器,那么您需要以编程方式添加它们,如上所示
  4. 如果您有任何过滤器或其他东西,那么您需要以编程方式将它们添加到ctx.
  5. server通过提供 URI 和实例来使用 Grizzly 实例进行初始化ResourceConfig
  6. 您已经以编程方式创建了WebappContextweb.xml,现在使用它的 deploy 方法将服务器实例传递给它。这将运行WebappContext配置并将其部署到server实例。

现在你有一个运行 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-assured 基本路径如下

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

如果您不想使用 REST-assured 那么

@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;
于 2016-09-25T08:16:52.683 回答