Skip to content

Commit c7fe319

Browse files
authored
Merge pull request #513 from hjgraca/idempotency-method-e2e-test
chore: add e2e tests for idempotency method
2 parents ce0de0f + a87e492 commit c7fe319

File tree

3 files changed

+159
-5
lines changed

3 files changed

+159
-5
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.IO;
19+
using System.Net.Http;
20+
using System.Text.Json;
21+
using System.Threading.Tasks;
22+
using Amazon.DynamoDBv2;
23+
using Amazon.Lambda.APIGatewayEvents;
24+
using Amazon.Lambda.Core;
25+
26+
namespace AWS.Lambda.Powertools.Idempotency.Tests.Handlers;
27+
28+
public class IdempotencyFunctionMethodDecorated
29+
{
30+
public bool MethodCalled;
31+
32+
public IdempotencyFunctionMethodDecorated(AmazonDynamoDBClient client)
33+
{
34+
Idempotency.Configure(builder =>
35+
builder
36+
.UseDynamoDb(storeBuilder =>
37+
storeBuilder
38+
.WithTableName("idempotency_table")
39+
.WithDynamoDBClient(client)
40+
));
41+
}
42+
43+
44+
public async Task<APIGatewayProxyResponse> Handle(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)
45+
{
46+
Idempotency.RegisterLambdaContext(context);
47+
var result= await InternalFunctionHandler(apigProxyEvent);
48+
49+
return result;
50+
}
51+
52+
private async Task<APIGatewayProxyResponse> InternalFunctionHandler(APIGatewayProxyRequest apigProxyEvent)
53+
{
54+
Dictionary<string, string> headers = new()
55+
{
56+
{"Content-Type", "application/json"},
57+
{"Access-Control-Allow-Origin", "*"},
58+
{"Access-Control-Allow-Methods", "GET, OPTIONS"},
59+
{"Access-Control-Allow-Headers", "*"}
60+
};
61+
62+
try
63+
{
64+
var address = JsonDocument.Parse(apigProxyEvent.Body).RootElement.GetProperty("address").GetString();
65+
var pageContents = await GetPageContents(address);
66+
var output = $"{{ \"message\": \"hello world\", \"location\": \"{pageContents}\" }}";
67+
68+
return new APIGatewayProxyResponse
69+
{
70+
Body = output,
71+
StatusCode = 200,
72+
Headers = headers
73+
};
74+
75+
}
76+
catch (IOException)
77+
{
78+
return new APIGatewayProxyResponse
79+
{
80+
Body = "{}",
81+
StatusCode = 500,
82+
Headers = headers
83+
};
84+
}
85+
}
86+
87+
[Idempotent]
88+
private async Task<string> GetPageContents(string address)
89+
{
90+
MethodCalled = true;
91+
92+
var client = new HttpClient();
93+
using var response = await client.GetAsync(address);
94+
using var content = response.Content;
95+
var pageContent = await content.ReadAsStringAsync();
96+
97+
return pageContent;
98+
}
99+
}

libraries/tests/AWS.Lambda.Powertools.Idempotency.Tests/IdempotencyTest.cs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
/*
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
*
3+
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
66
* A copy of the License is located at
7-
*
7+
*
88
* http://aws.amazon.com/apache2.0
9-
*
9+
*
1010
* or in the "license" file accompanying this file. This file is distributed
1111
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212
* express or implied. See the License for the specific language governing
1313
* permissions and limitations under the License.
1414
*/
1515

16+
using System;
17+
using System.Collections.Generic;
1618
using System.IO;
1719
using System.Text.Json;
1820
using System.Threading.Tasks;
1921
using Amazon.DynamoDBv2;
2022
using Amazon.DynamoDBv2.Model;
2123
using Amazon.Lambda.APIGatewayEvents;
24+
using Amazon.Lambda.TestUtilities;
2225
using AWS.Lambda.Powertools.Idempotency.Tests.Handlers;
2326
using AWS.Lambda.Powertools.Idempotency.Tests.Persistence;
2427
using FluentAssertions;
@@ -66,5 +69,57 @@ public async Task EndToEndTest()
6669
TableName = _tableName
6770
});
6871
scanResponse.Count.Should().Be(1);
72+
73+
// delete row dynamo
74+
var key = new Dictionary<string, AttributeValue>
75+
{
76+
["id"] = new AttributeValue { S = "testFunction.GetPageContents#ff323c6f0c5ceb97eed49121babcec0f" }
77+
};
78+
await _client.DeleteItemAsync(new DeleteItemRequest{TableName = _tableName, Key = key});
79+
}
80+
81+
[Fact]
82+
[Trait("Category", "Integration")]
83+
public async Task EndToEndTestMethod()
84+
{
85+
var function = new IdempotencyFunctionMethodDecorated(_client);
86+
87+
var options = new JsonSerializerOptions
88+
{
89+
PropertyNameCaseInsensitive = true
90+
};
91+
92+
var context = new TestLambdaContext
93+
{
94+
RemainingTime = TimeSpan.FromSeconds(30)
95+
};
96+
97+
var request = JsonSerializer.Deserialize<APIGatewayProxyRequest>(await File.ReadAllTextAsync("./resources/apigw_event2.json"),options);
98+
99+
var response = await function.Handle(request, context);
100+
function.MethodCalled.Should().BeTrue();
101+
102+
function.MethodCalled = false;
103+
104+
var response2 = await function.Handle(request, context);
105+
function.MethodCalled.Should().BeFalse();
106+
107+
// Assert
108+
JsonSerializer.Serialize(response).Should().Be(JsonSerializer.Serialize(response2));
109+
response.Body.Should().Contain("hello world");
110+
response2.Body.Should().Contain("hello world");
111+
112+
var scanResponse = await _client.ScanAsync(new ScanRequest
113+
{
114+
TableName = _tableName
115+
});
116+
scanResponse.Count.Should().Be(1);
117+
118+
// delete row dynamo
119+
var key = new Dictionary<string, AttributeValue>
120+
{
121+
["id"] = new AttributeValue { S = "testFunction.GetPageContents#ff323c6f0c5ceb97eed49121babcec0f" }
122+
};
123+
await _client.DeleteItemAsync(new DeleteItemRequest{TableName = _tableName, Key = key});
69124
}
70125
}

libraries/tests/AWS.Lambda.Powertools.Idempotency.Tests/Internal/IdempotentAspectTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ public void Handle_WhenIdempotencyOnSubMethodAnnotated_AndSecondCall_AndNotExpir
311311
// Arrange
312312
var store = Substitute.For<BasePersistenceStore>();
313313
store.SaveInProgress(Arg.Any<JsonDocument>(), Arg.Any<DateTimeOffset>(), Arg.Any<double>())
314-
.Throws(new IdempotencyItemAlreadyExistsException());
314+
.Returns(_ => throw new IdempotencyItemAlreadyExistsException());
315315

316316
Idempotency.Configure(builder => builder.WithPersistenceStore(store));
317317

@@ -327,7 +327,7 @@ public void Handle_WhenIdempotencyOnSubMethodAnnotated_AndSecondCall_AndNotExpir
327327
.Returns(record);
328328

329329
// Act
330-
var function = new IdempotencyInternalFunction(false);
330+
var function = new IdempotencyInternalFunction(true);
331331
Basket resultBasket = function.HandleRequest(product, new TestLambdaContext());
332332

333333
// assert

0 commit comments

Comments
 (0)