Skip to content

Commit c1108e6

Browse files
committed
Add tests
1 parent cb16615 commit c1108e6

5 files changed

Lines changed: 1424 additions & 0 deletions

File tree

test/dynamodb-mapper-v2/pom.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,30 @@
6969
<version>1.25.0</version>
7070
<scope>test</scope>
7171
</dependency>
72+
<dependency>
73+
<groupId>com.amazonaws</groupId>
74+
<artifactId>aws-java-sdk-dynamodb</artifactId>
75+
<version>1.12.797</version>
76+
<scope>test</scope>
77+
</dependency>
78+
<dependency>
79+
<groupId>com.amazonaws</groupId>
80+
<artifactId>aws-java-sdk-core</artifactId>
81+
<version>1.12.797</version>
82+
<scope>test</scope>
83+
</dependency>
84+
<dependency>
85+
<groupId>com.fasterxml.jackson.core</groupId>
86+
<artifactId>jackson-core</artifactId>
87+
<version>2.17.2</version>
88+
<scope>test</scope>
89+
</dependency>
90+
<dependency>
91+
<groupId>com.fasterxml.jackson.core</groupId>
92+
<artifactId>jackson-annotations</artifactId>
93+
<version>2.17.2</version>
94+
<scope>test</scope>
95+
</dependency>
7296
<dependency>
7397
<groupId>com.almworks.sqlite4java</groupId>
7498
<artifactId>sqlite4java</artifactId>
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
package software.amazon.awssdk.dynamodb.datamodeling;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.is;
5+
import static org.hamcrest.Matchers.nullValue;
6+
import static org.mockito.ArgumentMatchers.any;
7+
import static org.mockito.Mockito.verify;
8+
import static org.mockito.Mockito.when;
9+
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
import org.junit.Before;
14+
import org.junit.Test;
15+
import org.junit.runner.RunWith;
16+
import org.mockito.ArgumentCaptor;
17+
import org.mockito.Mock;
18+
import org.mockito.junit.MockitoJUnitRunner;
19+
20+
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
21+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
22+
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
23+
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
24+
25+
/**
26+
* Ported from Enhanced Client's GetItemOperationTest.
27+
* Verifies the exact request sent over the wire and the exact deserialization of the response.
28+
*/
29+
@RunWith(MockitoJUnitRunner.class)
30+
public class DynamoDBMapperGetItemWireTest {
31+
32+
private static final String TABLE_NAME = "TestTable";
33+
34+
@Mock
35+
private DynamoDbClient mockClient;
36+
37+
private DynamoDBMapper mapper;
38+
39+
// ---- Models ----
40+
41+
@DynamoDBTable(tableName = TABLE_NAME)
42+
public static class FakeItem {
43+
private String id;
44+
private String stringAttr;
45+
46+
@DynamoDBHashKey(attributeName = "id")
47+
public String getId() { return id; }
48+
public void setId(String id) { this.id = id; }
49+
50+
@DynamoDBAttribute(attributeName = "stringAttr")
51+
public String getStringAttr() { return stringAttr; }
52+
public void setStringAttr(String stringAttr) { this.stringAttr = stringAttr; }
53+
}
54+
55+
@DynamoDBTable(tableName = TABLE_NAME)
56+
public static class FakeItemWithSort {
57+
private String id;
58+
private String sort;
59+
private String data;
60+
61+
@DynamoDBHashKey(attributeName = "id")
62+
public String getId() { return id; }
63+
public void setId(String id) { this.id = id; }
64+
65+
@DynamoDBRangeKey(attributeName = "sort")
66+
public String getSort() { return sort; }
67+
public void setSort(String sort) { this.sort = sort; }
68+
69+
@DynamoDBAttribute(attributeName = "data")
70+
public String getData() { return data; }
71+
public void setData(String data) { this.data = data; }
72+
}
73+
74+
@Before
75+
public void setup() {
76+
mapper = new DynamoDBMapper(mockClient);
77+
}
78+
79+
// ---- Request verification tests (what goes over the wire) ----
80+
81+
@Test
82+
public void generateRequest_partitionKeyOnly() {
83+
when(mockClient.getItem(any(GetItemRequest.class)))
84+
.thenReturn(GetItemResponse.builder().build());
85+
86+
mapper.load(FakeItem.class, "test-id");
87+
88+
ArgumentCaptor<GetItemRequest> captor = ArgumentCaptor.forClass(GetItemRequest.class);
89+
verify(mockClient).getItem(captor.capture());
90+
91+
GetItemRequest actual = captor.getValue();
92+
Map<String, AttributeValue> expectedKey = new HashMap<>();
93+
expectedKey.put("id", AttributeValue.builder().s("test-id").build());
94+
95+
assertThat(actual.tableName(), is(TABLE_NAME));
96+
assertThat(actual.key(), is(expectedKey));
97+
assertThat(actual.consistentRead(), is(false));
98+
}
99+
100+
@Test
101+
public void generateRequest_partitionAndSortKey() {
102+
when(mockClient.getItem(any(GetItemRequest.class)))
103+
.thenReturn(GetItemResponse.builder().build());
104+
105+
mapper.load(FakeItemWithSort.class, "pk-val", "sk-val");
106+
107+
ArgumentCaptor<GetItemRequest> captor = ArgumentCaptor.forClass(GetItemRequest.class);
108+
verify(mockClient).getItem(captor.capture());
109+
110+
GetItemRequest actual = captor.getValue();
111+
Map<String, AttributeValue> expectedKey = new HashMap<>();
112+
expectedKey.put("id", AttributeValue.builder().s("pk-val").build());
113+
expectedKey.put("sort", AttributeValue.builder().s("sk-val").build());
114+
115+
assertThat(actual.tableName(), is(TABLE_NAME));
116+
assertThat(actual.key(), is(expectedKey));
117+
}
118+
119+
@Test
120+
public void generateRequest_consistentRead() {
121+
when(mockClient.getItem(any(GetItemRequest.class)))
122+
.thenReturn(GetItemResponse.builder().build());
123+
124+
DynamoDBMapperConfig config = DynamoDBMapperConfig.builder()
125+
.withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT)
126+
.build();
127+
128+
mapper.load(FakeItem.class, "test-id", null, config);
129+
130+
ArgumentCaptor<GetItemRequest> captor = ArgumentCaptor.forClass(GetItemRequest.class);
131+
verify(mockClient).getItem(captor.capture());
132+
133+
assertThat(captor.getValue().consistentRead(), is(true));
134+
}
135+
136+
@Test
137+
public void generateRequest_eventualConsistency() {
138+
when(mockClient.getItem(any(GetItemRequest.class)))
139+
.thenReturn(GetItemResponse.builder().build());
140+
141+
DynamoDBMapperConfig config = DynamoDBMapperConfig.builder()
142+
.withConsistentReads(DynamoDBMapperConfig.ConsistentReads.EVENTUAL)
143+
.build();
144+
145+
mapper.load(FakeItem.class, "test-id", null, config);
146+
147+
ArgumentCaptor<GetItemRequest> captor = ArgumentCaptor.forClass(GetItemRequest.class);
148+
verify(mockClient).getItem(captor.capture());
149+
150+
assertThat(captor.getValue().consistentRead(), is(false));
151+
}
152+
153+
@Test
154+
public void generateRequest_usingKeyObject() {
155+
when(mockClient.getItem(any(GetItemRequest.class)))
156+
.thenReturn(GetItemResponse.builder().build());
157+
158+
FakeItemWithSort keyObj = new FakeItemWithSort();
159+
keyObj.setId("pk-val");
160+
keyObj.setSort("sk-val");
161+
mapper.load(keyObj);
162+
163+
ArgumentCaptor<GetItemRequest> captor = ArgumentCaptor.forClass(GetItemRequest.class);
164+
verify(mockClient).getItem(captor.capture());
165+
166+
Map<String, AttributeValue> expectedKey = new HashMap<>();
167+
expectedKey.put("id", AttributeValue.builder().s("pk-val").build());
168+
expectedKey.put("sort", AttributeValue.builder().s("sk-val").build());
169+
170+
assertThat(captor.getValue().key(), is(expectedKey));
171+
}
172+
173+
@Test
174+
public void generateRequest_tableNameOverride() {
175+
when(mockClient.getItem(any(GetItemRequest.class)))
176+
.thenReturn(GetItemResponse.builder().build());
177+
178+
DynamoDBMapperConfig config = DynamoDBMapperConfig.builder()
179+
.withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement("OverriddenTable"))
180+
.build();
181+
182+
mapper.load(FakeItem.class, "test-id", null, config);
183+
184+
ArgumentCaptor<GetItemRequest> captor = ArgumentCaptor.forClass(GetItemRequest.class);
185+
verify(mockClient).getItem(captor.capture());
186+
187+
assertThat(captor.getValue().tableName(), is("OverriddenTable"));
188+
}
189+
190+
// ---- Response deserialization tests (what comes back from the wire) ----
191+
192+
@Test
193+
public void transformResponse_noItem() {
194+
when(mockClient.getItem(any(GetItemRequest.class)))
195+
.thenReturn(GetItemResponse.builder().build());
196+
197+
FakeItem result = mapper.load(FakeItem.class, "nonexistent");
198+
199+
assertThat(result, is(nullValue()));
200+
}
201+
202+
@Test
203+
public void transformResponse_emptyItemMap() {
204+
when(mockClient.getItem(any(GetItemRequest.class)))
205+
.thenReturn(GetItemResponse.builder().item(new HashMap<>()).build());
206+
207+
FakeItem result = mapper.load(FakeItem.class, "nonexistent");
208+
209+
assertThat(result, is(nullValue()));
210+
}
211+
212+
@Test
213+
public void transformResponse_correctlyDeserializesItem() {
214+
Map<String, AttributeValue> responseMap = new HashMap<>();
215+
responseMap.put("id", AttributeValue.builder().s("test-id").build());
216+
responseMap.put("stringAttr", AttributeValue.builder().s("test-value").build());
217+
218+
when(mockClient.getItem(any(GetItemRequest.class)))
219+
.thenReturn(GetItemResponse.builder().item(responseMap).build());
220+
221+
FakeItem result = mapper.load(FakeItem.class, "test-id");
222+
223+
assertThat(result.getId(), is("test-id"));
224+
assertThat(result.getStringAttr(), is("test-value"));
225+
}
226+
227+
@Test
228+
public void transformResponse_compositeKey_correctlyDeserializesItem() {
229+
Map<String, AttributeValue> responseMap = new HashMap<>();
230+
responseMap.put("id", AttributeValue.builder().s("pk-val").build());
231+
responseMap.put("sort", AttributeValue.builder().s("sk-val").build());
232+
responseMap.put("data", AttributeValue.builder().s("payload").build());
233+
234+
when(mockClient.getItem(any(GetItemRequest.class)))
235+
.thenReturn(GetItemResponse.builder().item(responseMap).build());
236+
237+
FakeItemWithSort result = mapper.load(FakeItemWithSort.class, "pk-val", "sk-val");
238+
239+
assertThat(result.getId(), is("pk-val"));
240+
assertThat(result.getSort(), is("sk-val"));
241+
assertThat(result.getData(), is("payload"));
242+
}
243+
244+
@Test
245+
public void transformResponse_missingAttributes_deserializesAsNull() {
246+
Map<String, AttributeValue> responseMap = new HashMap<>();
247+
responseMap.put("id", AttributeValue.builder().s("test-id").build());
248+
// stringAttr not in response
249+
250+
when(mockClient.getItem(any(GetItemRequest.class)))
251+
.thenReturn(GetItemResponse.builder().item(responseMap).build());
252+
253+
FakeItem result = mapper.load(FakeItem.class, "test-id");
254+
255+
assertThat(result.getId(), is("test-id"));
256+
assertThat(result.getStringAttr(), is(nullValue()));
257+
}
258+
259+
@Test
260+
public void transformResponse_extraAttributesInResponse_ignored() {
261+
Map<String, AttributeValue> responseMap = new HashMap<>();
262+
responseMap.put("id", AttributeValue.builder().s("test-id").build());
263+
responseMap.put("stringAttr", AttributeValue.builder().s("val").build());
264+
responseMap.put("unknownField", AttributeValue.builder().s("ignored").build());
265+
266+
when(mockClient.getItem(any(GetItemRequest.class)))
267+
.thenReturn(GetItemResponse.builder().item(responseMap).build());
268+
269+
FakeItem result = mapper.load(FakeItem.class, "test-id");
270+
271+
assertThat(result.getId(), is("test-id"));
272+
assertThat(result.getStringAttr(), is("val"));
273+
}
274+
}

0 commit comments

Comments
 (0)