Skip to content

Commit f790baa

Browse files
jeromevdlcarlzogh
andauthored
Add aws-lambda-java-tests module v1.0.0 (#192)
Co-authored-by: Carl Zogheib <[email protected]>
1 parent 593cbdb commit f790baa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2450
-1
lines changed

.github/workflows/aws-lambda-java-events.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ jobs:
3434
run: mvn -B package --file aws-lambda-java-serialization/pom.xml
3535
- name: Build events-sdk-transformer with Maven
3636
run: mvn -B package --file aws-lambda-java-events-sdk-transformer/pom.xml
37-
37+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# This workflow will be triggered if there will be changes to aws-lambda-java-tests
2+
# package and it builds the package and the packages that depend on it.
3+
4+
name: Java CI aws-lambda-java-tests
5+
6+
on:
7+
push:
8+
branches: [ master ]
9+
paths:
10+
- 'aws-lambda-java-tests/**'
11+
pull_request:
12+
branches: [ '*' ]
13+
paths:
14+
- 'aws-lambda-java-tests/**'
15+
16+
jobs:
17+
build:
18+
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v2
23+
- name: Set up JDK 1.8
24+
uses: actions/setup-java@v1
25+
with:
26+
java-version: 1.8
27+
28+
# Install base module
29+
- name: Install events with Maven
30+
run: mvn -B install --file aws-lambda-java-events/pom.xml
31+
- name: Install serialization with Maven
32+
run: mvn -B install --file aws-lambda-java-serialization/pom.xml
33+
34+
# Package target module
35+
- name: Package tests with Maven
36+
run: mvn -B package --file aws-lambda-java-tests/pom.xml
37+

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Check out the per-module release notes:
2121
- [aws-lambda-java-log4j2](aws-lambda-java-log4j2/RELEASE.CHANGELOG.md)
2222
- [aws-lambda-java-runtime-interface-client](aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md)
2323
- [aws-lambda-java-serialization](aws-lambda-java-serialization/RELEASE.CHANGELOG.md)
24+
- [aws-lambda-java-test](aws-lambda-java-tests/RELEASE.CHANGELOG.md)
2425

2526
# Where to get packages
2627
___
@@ -53,6 +54,12 @@ ___
5354
<artifactId>aws-lambda-java-runtime-interface-client</artifactId>
5455
<version>1.0.0</version>
5556
</dependency>
57+
<dependency>
58+
<groupId>com.amazonaws</groupId>
59+
<artifactId>aws-lambda-java-tests</artifactId>
60+
<version>1.0.0</version>
61+
<scope>test</scope>
62+
</dependency>
5663
```
5764

5865
[Gradle](https://gradle.org)
@@ -63,6 +70,7 @@ ___
6370
'com.amazonaws:aws-lambda-java-events-sdk-transformer:3.0.1'
6471
'com.amazonaws:aws-lambda-java-log4j2:1.2.0'
6572
'com.amazonaws:aws-lambda-java-runtime-interface-client:1.0.0'
73+
'com.amazonaws:aws-lambda-java-tests:1.0.0'
6674
```
6775

6876
[Leiningen](http://leiningen.org) and [Boot](http://boot-clj.com)
@@ -73,6 +81,7 @@ ___
7381
[com.amazonaws/aws-lambda-java-events-sdk-transformer "3.0.1"]
7482
[com.amazonaws/aws-lambda-java-log4j2 "1.2.0"]
7583
[com.amazonaws/aws-lambda-java-runtime-interface-client "1.0.0"]
84+
[com.amazonaws/aws-lambda-java-tests "1.0.0"]
7685
```
7786

7887
[sbt](http://www.scala-sbt.org)
@@ -83,6 +92,7 @@ ___
8392
"com.amazonaws" % "aws-lambda-java-events-sdk-transformer" % "3.0.1"
8493
"com.amazonaws" % "aws-lambda-java-log4j2" % "1.2.0"
8594
"com.amazonaws" % "aws-lambda-java-runtime-interface-client" % "1.0.0"
95+
"com.amazonaws" % "aws-lambda-java-tests" % "1.0.0"
8696
```
8797

8898
# Using aws-lambda-java-core
@@ -114,3 +124,7 @@ The purpose of this package is to allow developers to deploy their applications
114124
# Using aws-lambda-java-serialization
115125

116126
This package defines the Lambda serialization logic using in the aws-lambda-java-runtime-client library. It has no current standalone usage.
127+
128+
# Using aws-lambda-java-tests
129+
130+
This package provides utils to ease Lambda Java testing. Used with `aws-lambda-java-serialization` and `aws-lambda-java-events` to inject events in your JUnit tests.

aws-lambda-java-tests/README.md

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
2+
# Tests utility
3+
4+
The `aws-lambda-java-tests` module provides opinionated tools to ease Java Lambda testing. This is a test dependency.
5+
6+
**Key features**
7+
8+
* Load events from json files and get them deserialized into Java Events.
9+
* Inject Events directly in JUnit 5 tests, using the `@ParameterizedTest` annotation.
10+
11+
12+
## Background
13+
14+
When using Java for a Lambda function, you must implement the RequestHandler interface and provide input and output types:
15+
16+
```java
17+
public interface RequestHandler<I, O> {
18+
public O handleRequest(I input, Context context);
19+
}
20+
```
21+
22+
The input is automatically deserialized by the Lambda Java Runtime from a json event into the type you define,
23+
and the output is serialized into JSON from the output type. More info in the [docs](https://docs.aws.amazon.com/lambda/latest/dg/java-handler.html).
24+
25+
When you want to test your Lambda function and your handleRequest method, you cannot simply use JSON events files
26+
as some of the event fields may not be deserialized correctly.
27+
28+
For example, an SQS JSON event contains a list of "Records", while the [`SQSEvent`](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SQSEvent.java) use "records" with a lowercase.
29+
You can choose to modify the JSON input but it can be tedious and you generally want to keep the JSON event as you get it
30+
in the doc, the Lambda console or in your logs.
31+
32+
Now you can use the [aws-lambda-java-serialization](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-serialization) module to deserialize events. And this test library is using this module as a dependency to ease tests of lambda function handlers.
33+
34+
## Installation
35+
36+
To install this utility, add the following dependency to your project. Note that it's a test dependency.
37+
38+
```xml
39+
<dependency>
40+
<groupId>com.amazonaws</groupId>
41+
<artifactId>aws-lambda-java-tests</artifactId>
42+
<version>1.0.0</version>
43+
<scope>test</scope>
44+
</dependency>
45+
```
46+
47+
Also have surefire in your plugins:
48+
49+
```xml
50+
<build>
51+
<plugins>
52+
<plugin>
53+
<groupId>org.apache.maven.plugins</groupId>
54+
<artifactId>maven-surefire-plugin</artifactId>
55+
<version>2.22.2</version>
56+
</plugin>
57+
</plugins>
58+
</build>
59+
```
60+
61+
## Usage
62+
63+
### Events injection
64+
65+
A set of annotations can be used to inject Events and/or to validate handler responses against those Events.
66+
**All those annotations must be used in conjunction with the [`@ParameterizedTest`](https://junit.org/junit5/docs/current/api/org.junit.jupiter.params/org/junit/jupiter/params/ParameterizedTest.html) annotation from Junit 5.**
67+
68+
`ParameterizedTest` enables to inject arguments into a unit test, so you can run the same test one or more time with different parameters.
69+
See [the doc](https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests) for more details on this.
70+
71+
**Event**
72+
73+
The `@Event` annotation permits to inject one Event into a Junit test.
74+
75+
Example:
76+
77+
```java
78+
// the json file must be in the classpath (most often in src/test/resources)
79+
@ParameterizedTest
80+
@Event(value = "sqs/sqs_event.json", type = SQSEvent.class)
81+
public void testInjectSQSEvent(SQSEvent event) {
82+
// test your handleRequest method with this event as parameter
83+
}
84+
```
85+
86+
**Events**
87+
88+
The `@Events` annotation permits to inject multiple Events into a Junit test
89+
90+
Examples:
91+
92+
```java
93+
@ParameterizedTest
94+
@Events(
95+
events = {
96+
@Event("sqs/sqs_event.json"),
97+
@Event("sqs/sqs_event2.json"),
98+
},
99+
type = SQSEvent.class
100+
)
101+
public void testInjectEvents(SQSEvent event) {
102+
// test your handleRequest method with all the JSON events available in the sqs folder
103+
}
104+
105+
// OR simpler
106+
107+
// sqs folder must be in the classpath (most often in src/test/resources)
108+
@ParameterizedTest
109+
@Events(folder = "sqs", type = SQSEvent.class)
110+
public void testInjectEventsFromFolder(SQSEvent event) {
111+
// test your handleRequest method with all the JSON events available in the sqs folder
112+
}
113+
```
114+
115+
**HandlerParams**
116+
117+
The `@HandlerParams` is the most advanced one as it permits to provide both input and output as arguments to your tests.
118+
Thus you can validate your `handlerRequest` method by providing the output and asserting on the expected output.
119+
120+
```java
121+
122+
// Single event
123+
@ParameterizedTest
124+
@HandlerParams(
125+
event = @Event(value = "apigw/events/apigw_event.json", type = APIGatewayProxyRequestEvent.class),
126+
response = @Response(value = "apigw/responses/apigw_response.json", type = APIGatewayProxyResponseEvent.class))
127+
public void testSingleEventResponse(APIGatewayProxyRequestEvent event, APIGatewayProxyResponseEvent response) {
128+
}
129+
130+
// Multiple events in folder
131+
@ParameterizedTest
132+
@HandlerParams(
133+
events = @Events(folder = "apigw/events/", type = APIGatewayProxyRequestEvent.class),
134+
responses = @Responses(folder = "apigw/responses/", type = APIGatewayProxyResponseEvent.class))
135+
public void testMultipleEventsResponsesInFolder(APIGatewayProxyRequestEvent event, APIGatewayProxyResponseEvent response) {
136+
}
137+
138+
// Multiple events
139+
@HandlerParams(
140+
events = @Events(
141+
events = {
142+
@Event("apigw/events/apigw_event.json"),
143+
@Event("apigw/events/apigw_event2.json"),
144+
},
145+
type = APIGatewayProxyRequestEvent.class
146+
),
147+
responses = @Responses(
148+
responses = {
149+
@Response("apigw/responses/apigw_response.json"),
150+
@Response("apigw/responses/apigw_response2.json")
151+
},
152+
type = APIGatewayProxyResponseEvent.class
153+
)
154+
)
155+
public void testMultipleEventsResponses(APIGatewayProxyRequestEvent event, APIGatewayProxyResponseEvent response) {
156+
}
157+
```
158+
159+
If you cannot use those annotations (for example if you use TestNG), or if you want to load the events on your own, you can directly use the `EventLoader`, which is the underlying class that load the json events.
160+
161+
### EventLoader
162+
163+
`EventLoader` enables to load any Event from a JSON file and deserialize it into a Java Object.
164+
Either one from the [aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-events) library
165+
or your own Event.
166+
167+
EventLoader provides a load method for most of the pre-defined events:
168+
169+
```java
170+
APIGatewayV2HTTPEvent httpEvent =
171+
EventLoader.loadApiGatewayHttpEvent("apigw_http_event.json");
172+
173+
APIGatewayProxyRequestEvent restEvent =
174+
EventLoader.loadApiGatewayRestEvent("apigw_rest_event.json");
175+
176+
DynamodbEvent ddbEvent = EventLoader.loadDynamoDbEvent("ddb_event.json");
177+
178+
KinesisEvent kinesisEvent =
179+
EventLoader.loadKinesisEvent("kinesis_event.json");
180+
181+
ScheduledEvent eventBridgeEvent =
182+
EventLoader.loadScheduledEvent("eb_event.json");
183+
184+
S3Event s3Event = EventLoader.loadS3Event("s3_event.json");
185+
186+
SNSEvent snsEvent = EventLoader.loadSNSEvent("sns_event.json");
187+
188+
SQSEvent sqsEvent = EventLoader.loadSQSEvent("sqs_event.json");
189+
190+
// ... and many others
191+
```
192+
193+
Or you can load what you prefer with the generic method:
194+
195+
```java
196+
MyEvent myEvent = EventLoader.loadEvent("my_event.json", MyEvent.class);
197+
```
198+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### December 03, 2020
2+
`1.0.0`:
3+
- Initial release of AWS Lambda Java Tests

0 commit comments

Comments
 (0)