DynamoDB + Rake + Maven + Rack::Test

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

在我的一个名为SixNines.io的Ruby宠物网络应用程序中,我正在使用DynamoDB,这是由AWS提供的一种NoSQL云数据库。它的功能非常强大,但问题是很难创建一个集成测试,以确保我的代码与”真实”的DynamoDB服务器和表一起工作。让我向你展示如何解决这个问题。该代码是开源的,你可以在yegor256/sixnines GitHub存储库中查看。

首先,您需要使用由AWS创建的DynamoDB Local命令行工具进行测试。在进行集成测试之前,您需要启动它并在测试完成后停止。

为了使事情更简单,我建议您使用jcabi-dynamodb-maven-plugin,这是我几年前开发的一个Maven插件。您需要将pom.xml添加到您的代码库中,并从Rakefile启动/停止Maven,就像我在这里所做的一样。

首先,我要删除dynamodb-local/target目录,这是Maven保存临时文件的目录,以确保我们始终从头开始。

然后,我使用Process.spawn作为后台进程启动mvn install,并使用pid作为其进程ID(这在Windows上不起作用,只在Linux/Mac上有效)。然后我立即注册一个at_exit的Ruby钩子,如果Ruby因任何原因而死亡,该钩子将被执行。我相信很明显,我为什么要这样做——为了避免在Rake完成或终止后在后台运行垃圾。

请注意,我使用的是kill -TERM而不是kill -KILL,以便给Maven一个机会来完成所有工作,正确终止DynamoDB Local,关闭其TCP端口并退出。

接下来,我要检查sn-endpoints这个表在DynamoDB Local中的状态。如果服务器正在运行,它就应该存在。根据sn-endpoints.json中的JSON配置,它将由jcabi-dynamodb-maven-plugin创建。

然而,这个表可能不会立即准备好,因为需要时间来启动Maven、启动服务器并在其中创建表。这就是为什么,如果出现异常,我会捕获它,等待5秒钟然后重试。我会一直尝试多次,直到服务器准备好。最终它会准备好的。在我的MacBook上大约需要12-15秒,也就是2-3次尝试/异常。

我的类需要在集成测试期间知道如何连接到服务器。在生产环境中,它们需要连接到AWS,在测试中,它们必须知道我刚刚启动的DynamoDB本地实例。这就是我在Dynamo类中的内容,它负责与DynamoDB进行连接。它根据环境变量RACK_ENV的决定来确定连接位置,该变量在test__helper.rb中设置为"test"rake/testtask会在所有其他测试之前加载它,感谢其名称中的双下划线。

如果环境变量设置为"test"Dynamo将从YAML文件dynamodb-local/target/dynamo.yml中获取连接参数,该文件是由maven-resources-plugin:copy-resources创建的。DynamoDB Local数据库的TCP端口将在此处找到,以及DynamoDB的身份验证密钥和密码。

这是最容易的部分。我只需按照生产中的要求使用我的对象,并将它们连接到 DynamoDB 本地而不是 AWS。

为了测试整个应用程序,我使用 Rack::Test 进行一系列的 HTTP 调用。例如,在这里,我试图渲染 Jeff 的用户账户页面。它的 HTTP 响应代码应该是 200。

现在您可以从命令行运行整个测试。您可以在发布新版本时查看Rultor是如何运行它的:完整日志。此外,也可以在Travis中查看其运行方式:Travis链接。简而言之:

  • Rake试图运行default任务,该任务依赖于test

  • Rake 尝试运行 test,它依赖于 dynamo

  • Rake,在test任务中,使用此pom.xml在后台运行mvn install

  • Maven unpacks DynamoDB Local 安装包;

  • Maven 保留 一个随机的TCP端口,并将其值存储在${dynamo.port}中;

  • Maven saves ${dynamo.port} and key/secret pair info;

Maven 会保存 ${dynamo.port} 和密钥/密码对信息;

  • Maven starts DynamoDB Local,将其绑定到保留的TCP端口上;

  • Rake waits for DynamoDB Local availability on the reserved port;

Rake在保留端口上等待DynamoDB Local的可用性;

Ruby终止Maven并停止DynamoDB Local。

That’s it.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 16:46

sixnines availability badge   GitHub stars