Integration Testing with a Local DynamoDB Instance – 用本地DynamoDB实例进行集成测试

最后修改: 2018年 4月 2日

1. Overview


If we develop an application which uses Amazon’s DynamoDB, it can be tricky to develop integration tests without having a local instance.

如果我们开发的应用程序使用 Amazon 的 DynamoDB,那么在没有本地实例的情况下,开发集成测试就会很棘手。

In this tutorial, we’ll explore multiple ways of configuring, starting and stopping a local DynamoDB for our integration tests.


This tutorial also complements our existing DynamoDB article.


2. Configuration


2.1. Maven Setup


DynamoDB Local is a tool developed by Amazon which supports all the DynamoDB APIs. It doesn’t directly manipulate the actual DynamoDB tables in production but performs it locally instead.

DynamoDB Local是一个由Amazon开发的工具,它支持所有DynamoDB API。它不直接操作生产中的实际DynamoDB表,而是在本地进行操作。

First, we add the DynamoDB Local dependency to the list of dependencies in our Maven configuration:



Next, we also need to add the Amazon DynamoDB repository, since the dependency doesn’t exist in the Maven Central repository.

接下来,我们还需要添加Amazon DynamoDB资源库,因为Maven Central资源库中不存在该依赖项。

We can select the closest Amazon server to our current IP address geolocation:


    <name>DynamoDB Local Release Repository</name>

2.2. Add SQLite4Java Dependency


The DynamoDB Local uses the SQLite4Java library internally; thus, we also need to include the library files when we run the test. The SQLite4Java library files depend on the environment where the test is running, but Maven can pull them transitively once we declare the DynamoDBLocal dependency.

DynamoDB Local内部使用SQLite4Java库;因此,我们在运行测试时也需要包含该库文件。SQLite4Java库文件取决于测试运行的环境,但一旦我们声明了DynamoDBLocal的依赖关系,Maven就可以将其转发。

Next, we need to add a new build step to copy native libraries into a specific folder that we’ll define in the JVM system property later on.


Let’s copy the transitively-pulled SQLite4Java library files to a folder named native-libs:



2.3. Set the SQLite4Java System Property


Now, we’ll reference the previously created folder (where the SQLite4Java libraries are located), using a JVM system property named sqlite4java.library.path:


System.setProperty("sqlite4java.library.path", "native-libs");

In order to successfully run the test later, it’s mandatory to have all the SQLite4Java libraries in the folder defined by the sqlite4java.library.path system property. We must run Maven test-compile (mvn test-compile) at least once to fulfill the prerequisite.

为了以后成功运行测试,必须在sqlite4java.library.path系统属性定义的文件夹中拥有所有SQLite4Java库。我们必须至少运行一次Maven test-compile(mvn test-compile)来满足前提条件

3. Setting up the Test Database’s Lifecycle


We can define the code to create and start the local DynamoDB server in a setup method annotated with @BeforeClass; and, symmetrically, stop the server in a teardown method annotated with @AfterClass.


In the following example, we’ll start up the local DynamoDB server on port 8000 and make sure it’s stopped again after running our tests:


public class ProductInfoDAOIntegrationTest {
    private static DynamoDBProxyServer server;

    public static void setupClass() throws Exception {
        System.setProperty("sqlite4java.library.path", "native-libs");
        String port = "8000";
        server = ServerRunner.createServerFromCommandLineArgs(
          new String[]{"-inMemory", "-port", port});

    public static void teardownClass() throws Exception {


We can also run the local DynamoDB server on any available port instead of a fixed port using In this case, we must also configure the test to set the endpoint to the correct DynamoDB port:


public String getAvailablePort() throws IOException {
    ServerSocket serverSocket = new ServerSocket(0);
    return String.valueOf(serverSocket.getLocalPort());

4. Alternative Approach: Using @ClassRule


We can wrap the previous logic in a JUnit rule which performs the same action:


public class LocalDbCreationRule extends ExternalResource {
    private DynamoDBProxyServer server;

    public LocalDbCreationRule() {
        System.setProperty("sqlite4java.library.path", "native-libs");

    protected void before() throws Exception {
        String port = "8000";
        server = ServerRunner.createServerFromCommandLineArgs(
          new String[]{"-inMemory", "-port", port});

    protected void after() {

    protected void stopUnchecked(DynamoDBProxyServer dynamoDbServer) {
        try {
        } catch (Exception e) {
            throw new RuntimeException(e);

To use our custom rule, we’ll have to create and annotate an instance with @ClassRule as shown below. Again, the test will create and start the local DynamoDB server prior to the test class initialization.


Note that the access modifier of the test rule must be public in order to run the test:

注意,测试规则的访问修饰语必须是public ,以便运行测试。

public class ProductInfoRepositoryIntegrationTest {
    public static LocalDbCreationRule dynamoDB = new LocalDbCreationRule();



Before wrapping up, a very quick note – since DynamoDB Local uses the SQLite database internally, its performance doesn’t reflect the real performance in production.

在结束之前,有一个非常简短的说明–由于DynamoDB Local内部使用SQLite数据库,其性能并不能反映生产中的真实性能。

5. Conclusion


In this article, we’ve seen how to setup and configure DynamoDB Local to run integration tests.

在这篇文章中,我们已经看到了如何设置和配置DynamoDB Local来运行集成测试。

As always, the source code and the configuration example can be found over on Github.