junit5_使用JUnit5对DynamoDB应用程序进行单元测试

junit5

junit5

在上一篇文章中,我描述了新的Java 2 AWS开发工具包,它为调用不同AWS服务的Java客户端提供了非阻塞IO支持。 在本文中,我将介绍一种用于单元测试AWS DynamoDB调用的方法。

有几种方法可以启动DynamoDB的本地版本–

1. AWS提供了一个DynamoDB本地

2. Localstack提供了一种在本地启动大量AWS服务的方法

3. DynamoDB LocalDocker版本

4. Dynalite ,DynamoDB的基于节点的实现

现在可以对应用程序进行单元测试,我需要能够在测试运行之前使用以下选项之一启动DynamoDB的嵌入式版本,然后在测试完成后将其关闭。 我采用了三种方法:

1.使用JUnit 5扩展,该扩展在内部启动AWS DynamoDB Local,并在测试后将其调低。

2.使用测试容器启动Docker版本DynamoDB Local

3.使用测试容器启动DynaLite

JUnit5扩展

JUnit5扩展提供了方便的挂钩点来启动嵌入式版本的DynamoDB用于测试。 通过将DynamoDB Local版本作为Maven依赖项来工作:

dependencies {
    ...
 testImplementation("com.amazonaws:DynamoDBLocal:1.11.119")
    ...
}

这种依赖关系的一个复杂之处在于,DynamoDB Local与之交互的本机组件(dll,.so等)和将它们放置在正确的位置,我依赖于Gradle任务:

task copyNativeDeps(type: Copy) {
 mkdir "build/native-libs"
 from(configurations.testCompileClasspath) {
  include '*.dll'
  include '*.dylib'
  include '*.so'
 }
 into 'build/native-libs'
}

test {
 dependsOn copyNativeDeps
}

它将本机库放在build / native-libs文件夹中,扩展名在内部将此路径设置为系统属性:

System.setProperty("sqlite4java.library.path", libPath.toAbsolutePath().toString())

这是JUnit5扩展的代码库,所有这些都已经连接起来-https://github.com/bijukunjummen/boot-with dynamodb / blob / master / src / test / kotlin / sample / dyn / rules / LocalDynamoExtension.kt

使用此扩展程序的测试如下所示:

class HotelRepoTest {
    companion object {
        @RegisterExtension
        @JvmField
        val localDynamoExtension = LocalDynamoExtension()

        @BeforeAll
        @JvmStatic
        fun beforeAll() {
            val dbMigrator = DbMigrator(localDynamoExtension.syncClient!!)
            dbMigrator.migrate()
        }

    }
    @Test
    fun saveHotel() {
        val hotelRepo = DynamoHotelRepo(localDynamoExtension.asyncClient!!)
        val hotel = Hotel(id = "1", name = "test hotel", address = "test address", state = "OR", zip = "zip")
        val resp = hotelRepo.saveHotel(hotel)

        StepVerifier.create(resp)
                .expectNext(hotel)
                .expectComplete()
                .verify()
    }
}

该代码可以与功能齐全的DynamoDB进行交互。

DynamoDB本地Docker的

该JUnit5扩展方法非常有效,但它需要与本地二进制一个额外的依赖在被拉到一个更简洁的方法可以是使用好。 Testcontainers旋转起来DynamoDB本地下列方式的泊坞窗版本:

class HotelRepoLocalDynamoTestContainerTest {
    @Test
    fun saveHotel() {
        val hotelRepo = DynamoHotelRepo(getAsyncClient(dynamoDB))
        val hotel = Hotel(id = "1", name = "test hotel", address = "test address", state = "OR", zip = "zip")
        val resp = hotelRepo.saveHotel(hotel)

        StepVerifier.create(resp)
                .expectNext(hotel)
                .expectComplete()
                .verify()
    }



    companion object {
        val dynamoDB: KGenericContainer = KGenericContainer("amazon/dynamodb-local:1.11.119")
                .withExposedPorts(8000)

        @BeforeAll
        @JvmStatic
        fun beforeAll() {
            dynamoDB.start()
        }

        @AfterAll
        @JvmStatic
        fun afterAll() {
            dynamoDB.stop()
        }

        fun getAsyncClient(dynamoDB: KGenericContainer): DynamoDbAsyncClient {
            val endpointUri = "http://" + dynamoDB.getContainerIpAddress() + ":" +
                    dynamoDB.getMappedPort(8000)
            val builder: DynamoDbAsyncClientBuilder = DynamoDbAsyncClient.builder()
                    .endpointOverride(URI.create(endpointUri))
                    .region(Region.US_EAST_1)
                    .credentialsProvider(StaticCredentialsProvider
                            .create(AwsBasicCredentials
                                    .create("acc", "sec")))
            return builder.build()
        }

        ...
    }
}

该代码在一个随机的未占用端口上启动DynamoDB并提供此信息,以便可以使用此信息创建客户端。 根据此处报告的问题,我不得不采取一些Kotlin解决方法

使用Dynalite的

Dynalite是DynamoDB的基于javascript的实现,可以使用TestContainer方法再次运行以进行测试。 但是,这次已经有了DynaliteTestContainer模块。 我发现它不支持JUnit5,并发送了Pull请求来提供这种支持,在迭代中可以使用原始docker镜像,这就是测试的样子:

class HotelRepoDynaliteTestContainerTest {
    @Test
    fun saveHotel() {
        val hotelRepo = DynamoHotelRepo(getAsyncClient(dynamoDB))
        val hotel = Hotel(id = "1", name = "test hotel", address = "test address", state = "OR", zip = "zip")
        val resp = hotelRepo.saveHotel(hotel)

        StepVerifier.create(resp)
                .expectNext(hotel)
                .expectComplete()
                .verify()
    }

    companion object {
        val dynamoDB: KGenericContainer = KGenericContainer("quay.io/testcontainers/dynalite:v1.2.1-1")
                .withExposedPorts(4567)

        @BeforeAll
        @JvmStatic
        fun beforeAll() {
            dynamoDB.start()
            val dbMigrator = DbMigrator(getSyncClient(dynamoDB))
            dbMigrator.migrate()
        }

        @AfterAll
        @JvmStatic
        fun afterAll() {
            dynamoDB.stop()
        }

        fun getAsyncClient(dynamoDB: KGenericContainer): DynamoDbAsyncClient {
            val endpointUri = "http://" + dynamoDB.getContainerIpAddress() + ":" +
                    dynamoDB.getMappedPort(4567)
            val builder: DynamoDbAsyncClientBuilder = DynamoDbAsyncClient.builder()
                    .endpointOverride(URI.create(endpointUri))
                    .region(Region.US_EAST_1)
                    .credentialsProvider(StaticCredentialsProvider
                            .create(AwsBasicCredentials
                                    .create("acc", "sec")))
            return builder.build()
        }
        ...
    }
}

结论

所有这些方法对于能够测试与DynamoDB的集成都是有用的。 我个人的喜好是使用TestContainers方法,如果通过JUnit5扩展方法可以使用其他Docker代理,则可以使用。 在我的github存储库中提供了使用这三种方法进行了全面工作测试的示例– https://github.com/bijukunjummen/boot-with-dynamodb

翻译自: https://www.javacodegeeks.com/2019/01/testing-dynamodb-using-junit5.html

junit5

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值