§编写功能测试
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 进行测试
发现此文档中的错误?此页面的源代码可以在 这里 找到。在阅读了 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?请访问 我们的社区论坛,与社区开始对话。