1+ package io.andrewohara.dynamokt
2+
3+ import io.kotest.assertions.throwables.shouldThrow
4+ import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
5+ import io.kotest.matchers.collections.shouldHaveSize
6+ import io.kotest.matchers.nulls.shouldNotBeNull
7+ import io.kotest.matchers.types.shouldBeInstanceOf
8+ import org.http4k.aws.AwsSdkAsyncClient
9+ import org.http4k.connect.amazon.dynamodb.FakeDynamoDb
10+ import org.junit.jupiter.api.Test
11+ import software.amazon.awssdk.auth.credentials.AwsBasicCredentials
12+ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient
13+ import software.amazon.awssdk.enhanced.dynamodb.Key
14+ import software.amazon.awssdk.regions.Region
15+ import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient
16+ import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException
17+ import java.util.concurrent.ExecutionException
18+
19+ private const val TABLE_NAME = " INSERT_NAME_OF_YOUR_TABLE_HERE"
20+
21+ class GH9Test {
22+
23+ private val enhancedClient by lazy {
24+ DynamoDbEnhancedAsyncClient .builder()
25+ .dynamoDbClient(
26+ DynamoDbAsyncClient .builder()
27+ .httpClient(AwsSdkAsyncClient (FakeDynamoDb ()))
28+ .credentialsProvider { AwsBasicCredentials .create(" key" , " id" ) }
29+ .region(Region .CA_CENTRAL_1 )
30+ .build()
31+ )
32+ .build()
33+ }
34+
35+ @Test
36+ fun `get item with wrong schema` () {
37+ val legacyClient = enhancedClient
38+ .table(TABLE_NAME , DataClassTableSchema (TestEntityV1 ::class ))
39+ .also { it.createTable().get() }
40+
41+ val entity1 = TestEntityV1 (id = " valid" , name = " valid name" )
42+ val entity2 = TestEntityV1 (id = " invalid" , name = null )
43+
44+ legacyClient.putItem(entity1).shouldNotBeNull().get()
45+ legacyClient.putItem(entity2).shouldNotBeNull().get()
46+
47+ val newClient = enhancedClient
48+ .table(TABLE_NAME , DataClassTableSchema (TestEntityV2 ::class ))
49+
50+ shouldThrow<ExecutionException > {
51+ newClient.getItem(Key .builder().partitionValue(" invalid" ).build()).get()
52+ }.cause.shouldBeInstanceOf<IllegalArgumentException >()
53+ }
54+
55+ @Test
56+ fun `get item from missing table` () {
57+ val testClient = enhancedClient
58+ .table(TABLE_NAME , DataClassTableSchema (TestEntityV1 ::class ))
59+
60+ shouldThrow<ExecutionException > {
61+ testClient.getItem(Key .builder().partitionValue(" foo" ).build()).get()
62+ }.cause.shouldBeInstanceOf<ResourceNotFoundException >()
63+ }
64+
65+ @Test
66+ fun `mapping error on scan` () {
67+ val legacyClient = enhancedClient
68+ .table(TABLE_NAME , DataClassTableSchema (TestEntityV1 ::class ))
69+ .also { it.createTable().get() }
70+
71+ val entity1 = TestEntityV1 (id = " valid" , name = " valid name" )
72+ val entity2 = TestEntityV1 (id = " invalid" , name = null )
73+
74+ legacyClient.putItem(entity1).shouldNotBeNull().get()
75+ legacyClient.putItem(entity2).shouldNotBeNull().get()
76+
77+ val newClient = enhancedClient
78+ .table(TABLE_NAME , DataClassTableSchema (TestEntityV2 ::class ))
79+
80+ shouldThrow<ExecutionException > {
81+ newClient.scan().subscribe {
82+ it.items().shouldHaveSize(3 )
83+ it.items().shouldContainExactlyInAnyOrder(entity1, entity2)
84+ }.get()
85+ }.cause.shouldBeInstanceOf<IllegalArgumentException >()
86+ }
87+ }
88+
89+ data class TestEntityV2 (
90+ @DynamoKtPartitionKey
91+ var id : String ,
92+ val name : String ,
93+ val otherField : String = " abc"
94+ )
95+
96+ data class TestEntityV1 (
97+ @DynamoKtPartitionKey
98+ var id : String ,
99+ val name : String? ,
100+ val otherField : String = " abc"
101+ )
0 commit comments