到目前为止,我们一直在开发未经测试的wiki实施。这当然不是一个好习惯,所以让我们看看如何编写Vert.x代码的测试。
入门
该vertx-unit
模块提供了用于在Vert.x中测试异步操作的实用程序。除此之外,您可以使用您的测试框架,如JUnit。
使用JUnit,所需的Maven依赖关系如下所示:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-unit</artifactId>
<scope>test</scope>
</dependency>
JUnit测试需要用VertxUnitRunner
跑步者注释才能使用这些vertx-unit
特性:
@RunWith(VertxUnitRunner.class)
public class SomeTest {
// (...)
}
对于那个跑步者,JUnit测试和生命周期方法接受一个TestContext
论点。该对象提供对基本断言的访问权限,用于存储数据的上下文以及我们将在本节中看到的一些面向异步的助手。
为了说明这一点,让我们考虑一个异步场景,我们要检查定时器任务是否被调用过一次,并且定期任务被调用了3次。由于该代码是异步的,所以测试方法在测试完成之前退出,因此使测试通过或失败也需要以异步方式完成:
@Test /*(timeout=5000)*/ (8)
public void async_behavior(TestContext context) { (1)
Vertx vertx = Vertx.vertx(); (2)
context.assertEquals("foo", "foo"); (3)
Async a1 = context.async(); (4)
Async a2 = context.async(3); (5)
vertx.setTimer(100, n -> a1.complete()); (6)
vertx.setPeriodic(100, n -> a2.countDown()); (7)
}
TestContext
是跑步者提供的参数。由于我们在单元测试中,我们需要创建一个Vert.x上下文。
这是一个基本
TestContext
断言的例子。我们得到第一个
Async
可以稍后完成(或失败)的对象。该
Async
对象用作3次调用后成功完成的倒计时。当计时器启动时我们完成。
每个周期性任务刻度触发倒计时。所有
Async
对象完成后,测试通过。异步测试用例有一个默认(长)超时,但可以通过JUnit
@Test
注释覆盖它。
测试数据库操作
数据库服务非常适合编写测试。
我们首先需要部署数据库垂直。我们将配置JDBC连接为带有内存存储的HSQLDB,一旦成功,我们将为我们的测试用例获取服务代理。
由于涉及这些操作,因此我们在生命周期方法之前 / 之后利用JUnit :
private Vertx vertx;
private WikiDatabaseService service;
@Before
public void prepare(TestContext context) throws InterruptedException {
vertx = Vertx.vertx();
JsonObject conf = new JsonObject() (1)
.put(WikiDatabaseVerticle.CONFIG_WIKIDB_JDBC_URL, "jdbc:hsqldb:mem:testdb;shutdown=true")
.put(WikiDatabaseVerticle.CONFIG_WIKIDB_JDBC_MAX_POOL_SIZE, 4);
vertx.deployVerticle(new WikiDatabaseVerticle(), new DeploymentOptions().setConfig(conf),
context.asyncAssertSuccess(id -> (2)
service = WikiDatabaseService.createProxy(vertx, WikiDatabaseVerticle.CONFIG_WIKIDB_QUEUE)));
}
我们只覆盖一些垂直设置,其他设置将具有默认值。
asyncAssertSuccess
对于提供一个检查异步操作是否成功的处理程序非常有用。有一个没有参数的变体,以及像这样的变体,我们可以将结果链接到另一个处理程序。
清理Vert.x上下文很简单,我们再次使用它asyncAssertSuccess
来确保没有遇到错误:
@After
public void finish(TestContext context) {
vertx.close(context.asyncAssertSuccess());
}
服务操作本质上是CRUD操作,因此将JUnit测试用例组合起来是一种很好的测试方法:
@Test
public void crud_operations(TestContext context) {
Async async = context.async();
service.createPage("Test", "Some content", context.asyncAssertSuccess(v1 -> {
service.fetchPage("Test", context.asyncAssertSuccess(json1 -> {
context.assertTrue(json1.getBoolean("found"));
context.assertTrue(json1.containsKey("id"));
context.assertEquals("Some content", json1.getString("rawContent"));
service.savePage(json1.getInteger("id"), "Yo!", context.asyncAssertSuccess(v2 -> {
service.fetchAllPages(context.asyncAssertSuccess(array1 -> {
context.assertEquals(1, array1.size());
service.fetchPage("Test", context.asyncAssertSuccess(json2 -> {
context.assertEquals("Yo!", json2.getString("rawContent"));
service.deletePage(json1.getInteger("id"), v3 -> {
service.fetchAllPages(context.asyncAssertSuccess(array2 -> {
context.assertTrue(array2.isEmpty());
async.complete(); (1)
}));
});
}));
}));
}));
}));
}));
async.awaitSuccess(5000); (2)
}
这是唯一
Async
最终完成的地方。这是退出测试用例方法并依赖JUnit超时的替代方法。这里测试用例线程的执行一直等到
Async
完成或超时时间结束。