[英]Testing my AWS Lambda function with a fake S3Event
我正在為從 S3 觸發的 AWS Lambda 實現 Java 8 包,獲取一些文件數據並放入另一個 S3 存儲桶。
這是我當前的Handler
程序:
public class Handler implements RequestHandler<S3Event, Void> {
private static final String TARGET_BUCKET = "some-bucket";
private AmazonS3Client s3Client = new AmazonS3Client(new DefaultAWSCredentialsProviderChain());
private Runner runner = new Runner(s3Client, TARGET_BUCKET);
@Override
public Void handleRequest(S3Event s3Event, Context context) {
runner.run(s3Event, context);
return null;
}
}
我已將業務邏輯移至我的Runner
類,以便我可以正確測試它(遵循AWS Lambda 最佳實踐白皮書)。
但是,我很難了解如何通過假S3Event
來測試我的run
功能。
我目前的測試是:
@Test
public void putsDataIntoS3() throws IOException {
runner.run(new ObjectMapper().readValue(loadJsonFromFile("s3-event.json"), S3Event.class), context);
assertTrue(true);
}
其中loadJsonFromFile
使用我傳遞的文件名獲取資源,將其轉換為輸入流,然后轉換為String
。
但是,這會導致錯誤:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.amazonaws.services.lambda.runtime.events.S3Event]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
所以我的問題是,如何通過傳遞假的S3Event
JSON 來正確測試我的run
功能?
這些是我正在使用的與 aws 相關的依賴項:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.455</version>
</dependency>
我可以像這樣使用S3Event.parseJson
函數:我也見過parseJson
函數,我可以像這樣使用它:
@Test
public void putsFilteredDataIntoS3() throws IOException {
runner.run(new S3Event(S3Event.parseJson(loadJsonFromFile("s3-event.json")).getRecords()), context);
assertTrue(true);
}
但是做這一切是最佳實踐嗎?
您可以使用 Mockito 庫並嘗試模擬此S3Event
。
從 JSON 創建S3Event
的另一個選項:
S3EventNotification notification = S3EventNotification.parseJson(loadJsonFromFile("s3-event.json"));
S3Event event = new S3Event(notification.getRecords());
編輯:第三個選項是將您的aws-lambda-java-events
更新到版本2.2.4
,他們在其中為S3Event
添加了默認構造函數,因此您可以像這樣反序列化它:
objectMapper.readValue(loadJsonFromFile("s3-event.json"), S3Event.class)
如果您使用的是 AWS 開發工具包的版本 2,最簡單的方法是使用亞馬遜內部使用的反序列化器:
AWS Lambda Java 運行時序列化
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-serialization</artifactId>
<version>1.0.0</version>
</dependency>
它的工作原理如下:
PojoSerializer<S3Event> s3EventSerializer = LambdaEventSerializers.serializerFor(S3Event.class, ClassLoader.getSystemClassLoader());
S3Event event = s3EventSerializer.fromJson(inputStream);
有一件重要的事情需要了解(AWS SDK 版本 2 與版本 1) :
如果您的 JSON 有問題(不兼容的字段值或 JodaTime 庫不在類路徑中),則序列化程序什么也不說並激活 AWS SDK 1 回退。 最后你會得到這樣的錯誤:
java.lang.ClassNotFoundException: com.amazonaws.services.s3.event.S3EventNotification$S3EventNotificationRecord.
這個消息是錯誤的。 AWS 解串器與版本 2 和版本 1 完美配合。庫本身不依賴於 SDK(無論是 1 還是 2)。 很可能您需要檢查 JSON。
我一直在 S3Event 和 S3NotificationEvent 的兩個包之間遇到問題。
我無法將 json 解析為 com.amazonaws.services.lambda.runtime.events.S3EventNotification 由於
https://github.com/aws/aws-lambda-java-libs/issues/151
閱讀 JSON 后,我得到了com.amazonaws.services.s3.event.S3EventNotification
但 FunctionHandler 需要來自 com.amazonaws.services.lambda.runtime.events.S3Event 的com.amazonaws.services.lambda.runtime.events.S3Event
。
我做不到S3Event(notification.records)
。
所以我不得不編寫自己的方法來轉換類
fun test() {
val fileContent = this::class.java.classLoader.getResource("s3-event.json").readText()
val s3NotificationEvent = ObjectMapper().registerKotlinModule().readValue(fileContent, S3EventNotification::class.java)
val s3Event = S3Event(
s3NotificationEvent.records.map {
it.toRuntimeS3NotificationRecord()
}
)
)
fun S3EventNotification.S3EventNotificationRecord.toRuntimeS3NotificationRecord(): com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3EventNotificationRecord {
return com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3EventNotificationRecord(
awsRegion, eventName, eventSource,
eventTime.toString(), eventVersion,
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.RequestParametersEntity(requestParameters.sourceIPAddress),
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.ResponseElementsEntity(responseElements.getxAmzId2(), responseElements.getxAmzRequestId()),
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3Entity(
s3.configurationId,
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3BucketEntity(
s3.bucket.name,
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.UserIdentityEntity(s3.bucket.ownerIdentity.principalId),
s3.bucket.arn
),
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3ObjectEntity(s3.`object`.key, s3.`object`.sizeAsLong, s3.`object`.geteTag(), s3.`object`.versionId, s3.`object`.sequencer),
s3.s3SchemaVersion
),
com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.UserIdentityEntity(userIdentity.principalId)
)
}
您可以使用EventLoader
類:
S3Event s3Event = EventLoader.loadS3Event("s3-event.json");
將此依賴項添加到您的項目中:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-tests</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
有關此主題的更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.