文档

§编写功能测试

Play 提供了许多类和便捷方法来帮助进行功能测试。大多数这些方法可以在 play.test 包或 Helpers 类中找到。

您可以通过导入以下内容来添加这些方法和类

import play.test.*;
import static play.test.Helpers.*;

§创建用于测试的 Application 实例

Play 通常需要一个正在运行的 Application 作为上下文。为了提供测试环境,Play 提供了用于生成用于测试的新应用程序实例的帮助程序。

import static play.test.Helpers.*;
Application fakeApp = fakeApplication();

Application fakeAppWithMemoryDb = fakeApplication(inMemoryDatabase("test"));

§注入测试

如果您使用 Guice 进行 依赖注入,那么可以 直接构建 用于测试的 Application。您还可以注入测试类中可能需要的任何成员。通常,最佳实践是在功能测试中仅注入成员,并在单元测试中手动创建实例。

@Inject Application application;

@Before
public void setup() {
  Module testModule =
      new AbstractModule() {
        @Override
        public void configure() {
          // Install custom test binding here
        }
      };

  GuiceApplicationBuilder builder =
      new GuiceApplicationLoader()
          .builder(new Context(Environment.simple()))
          .overrides(testModule);
  Guice.createInjector(builder.applicationModule()).injectMembers(this);

  Helpers.start(application);
}

@After
public void teardown() {
  Helpers.stop(application);
}

§使用应用程序进行测试

要使用 Application 运行测试,您可以执行以下操作

@Test
public void findById() {
  running(
      fakeApplication(inMemoryDatabase("test")),
      () -> {
        Computer macintosh = Computer.findById(21l);
        assertEquals("Macintosh", macintosh.name);
        assertEquals("1984-01-24", formatted(macintosh.introduced));
      });
}

您还可以扩展 WithApplication,这将自动确保为每个测试方法启动和停止应用程序

public class FunctionalTest extends WithApplication {

§使用 Guice 应用程序进行测试

要使用 Guice 创建的 Application 运行测试,您可以执行以下操作

@Test
public void findById() {
  ClassLoader classLoader = classLoader();
  Application application =
      new GuiceApplicationBuilder()
          .in(new Environment(new File("path/to/app"), classLoader, Mode.TEST))
          .build();

  running(
      application,
      () -> {
        Computer macintosh = Computer.findById(21l);
        assertEquals("Macintosh", macintosh.name);
        assertEquals("1984-01-24", macintosh.introduced);
      });
}

请注意,使用 Guice 进行测试时,有不同的方法可以自定义 Application 创建。

§通过路由测试控制器操作

使用正在运行的应用程序,您可以从路由的路径中检索操作引用并调用它。这还允许您使用 RequestBuilder,它创建了一个假请求

import play.mvc.Http.RequestBuilder;
@Test
public void testBadRoute() {
  RequestBuilder request = Helpers.fakeRequest().method(GET).uri("/xx/Kiwi");

  Result result = route(app, request);
  assertEquals(NOT_FOUND, result.status());
}

也可以使用反向路由器直接创建 RequestBuilder,并避免硬编码路由器路径

@Test
public void testGoodRouteCall() {
  RequestBuilder request = Helpers.fakeRequest(routes.HomeController.index());

  Result result = route(app, request);
   assertEquals(OK, result.status());
}

注意:反向路由器不会执行操作,而是仅提供一个包含信息的 Call,这些信息将用于创建 RequestBuilder,并随后使用 Helpers.route(Application, RequestBuilder) 本身调用操作。这就是为什么即使操作接收 Http.Request 作为参数,在测试中使用反向路由器创建 Http.RequestBuilder 时,也不需要传递 Http.Request 的原因。

§使用服务器进行测试

有时您想在测试中测试真实的 HTTP 堆栈。您可以通过启动测试服务器来实现。

@Test
public void testInServer() throws Exception {
  TestServer server = testServer(3333);
  running(
      server,
      () -> {
        try (WSClient ws = WSTestClient.newClient(3333)) {
          CompletionStage<WSResponse> completionStage = ws.url("/").get();
          WSResponse response = completionStage.toCompletableFuture().get();
          assertEquals(OK, response.getStatus());
        } catch (Exception e) {
          logger.error(e.getMessage(), e);
        }
      });
}

就像存在一个 WithApplication 类一样,也存在一个 WithServer,您可以扩展它来自动启动和停止一个 TestServer 用于您的测试。

public class ServerFunctionalTest extends WithServer {

  @Test
  public void testInServer() throws Exception {
    OptionalInt optHttpsPort = testServer.getRunningHttpsPort();
    String url;
    int port;
    if (optHttpsPort.isPresent()) {
      port = optHttpsPort.getAsInt();
      url = "https://127.0.0.1:" + port;
    } else {
      port = testServer.getRunningHttpPort().getAsInt();
      url = "https://127.0.0.1:" + port;
    }
    try (WSClient ws = play.test.WSTestClient.newClient(port)) {
      CompletionStage<WSResponse> stage = ws.url(url).get();
      WSResponse response = stage.toCompletableFuture().get();
      assertEquals(NOT_FOUND, response.getStatus());
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

§使用浏览器进行测试

如果您想从 Web 浏览器中测试您的应用程序,您可以使用 Selenium WebDriver。Play 将为您启动 WebDriver,并将其包装在 FluentLenium 提供的便捷 API 中。

@Test
public void runInBrowser() {
  running(
      testServer(),
      HTMLUNIT,
      browser -> {
        browser.goTo("/");
        assertEquals("Welcome to Play!", browser.el("#title").text());
        browser.$("a").click();
        assertEquals("login", browser.url());
      });
}

当然,还有 WithBrowser 类,用于自动为每个测试打开和关闭浏览器。

public class BrowserFunctionalTest extends WithBrowser {

  @Test
  public void runInBrowser() {
    browser.goTo("/");
    assertNotNull(browser.el("title").text());
  }
}

下一步:使用 Guice 进行测试


发现此文档中的错误?此页面的源代码可以在 这里 找到。在阅读了 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?请访问 我们的社区论坛,与社区开始对话。