Groovy解析含multipart/form-data的APIGatewayProxyRequestEvent遇问题
问题背景
我正尝试将一款清理CSV/Excel文件的命令行应用转换为AWS Lambda函数,已完成上传但遇到依赖问题。为测试关键功能,针对函数代码编写了Spock单元测试,但测试失败。
相关测试与代码
测试代码
package com.mikebuyshouses.dncscrubber.awsServices import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent import com.mikebuyshouses.dncscrubber.awsServices.providers.TestPathProvider import com.mikebuyshouses.dncscrubber.utils.FileUtils import spock.lang.Specification class ApiRequestHandlerTest extends Specification { def "parseRequestEvent should actually write the input file from the request event"() { setup: def stubRequestEvent = Stub(APIGatewayProxyRequestEvent) stubRequestEvent.getHeaders() >> ["Content-Type": "multipart/form-data;boundary=YRPyKRi1Bb3sIDcW"] stubRequestEvent.getIsBase64Encoded() >> true; stubRequestEvent.getBody() >> """ ------WebKitFormBoundaryYRPyKRi1Bb3sIDcW\r Content-Disposition: form-data; name="inputFile"; filename="test.csv"\r Content-Type: text/csv\r \r Number,Sale Date,Address,City,State,Zip,Parcel,Township,Removed,Removed Date,Bankruptcy #,Redemption Days,Cause #,Receive Date,Receive Time,Total Judgement,Plaintiff,Et al,Attorney,Phone,User Fee,Sheriff Fee,Ad Cost,Delinquent Tax,Total Fees,Defendant,Judgement,Interest 1,Interest 2,Additional Charges,Lien Holder 1,Lien Holder 1 Judgement,Lien Holder 1 Interest 1,Lien Holder 1 Interest 2,Lien Holder 1 Additional Charges,Lien Holder 2,Lien Holder 2 Judgement,Lien Holder 2 Interest 1,Lien Holder 2 Interest 2,Lien Holder 2 Additional Charges,Lien Holder 3,Lien Holder 3 Judgement,Lien Holder 3 Interest 1,Lien Holder 3 Interest 2,Lien Holder 3 Additional Charges,Lien Holder 4,Lien Holder 4 Judgement,Lien Holder 4 Interest 1,Lien Holder 4 Interest 2,Lien Holder 4 Additional Charges,Lien Holder 5,Lien Holder 5 Judgement,Lien Holder 5 Interest 1,Lien Holder 5 Interest 2,Lien Holder 5 Additional Charges,Lien Holder 6,Lien Holder 6 Judgement,Lien Holder 6 Interest 1,Lien Holder 6 Interest 2,Lien Holder 6 Additional Charges,Lien Holder 7,Lien Holder 7 Judgement,Lien Holder 7 Interest 1,Lien Holder 7 Interest 2,Lien Holder 7 Additional Charges,Lien Holder 8,Lien Holder 8 Judgement,Lien Holder 8 Interest 1,Lien Holder 8 Interest 2,Lien Holder 8 Additional Charges,Lien Holder 9,Lien Holder 9 Judgement,Lien Holder 9 Interest 1,Lien Holder 9 Interest 2,Lien Holder 9 Additional Charges,,Grand Total\r 1,09/15/2023,1001 Main Street,Indianapolis,IN,46220,,BRO,N,,,,123456789MF123456,07/14/2023,,44202.67,FAKE BANK,,CARLISLE,(216) 555-1234,300,66,345.42,0,711.42,DOUGLAS H LOPEZ,44202.67,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,0,0,0,0,,44914.09\r \r ------WebKitFormBoundaryYRPyKRi1Bb3sIDcW--\r """.bytes.encodeBase64() ApiRequestHandler apiRequestHandler = new ApiRequestHandler().with { ApiRequestHandler handler -> handler.pathProvider = new TestPathProvider(); return handler; } when: apiRequestHandler.parseRequestEvent(stubRequestEvent) then: new File("${FileUtils.TestDirectoryPath}/${FileUtils.InputPathPart}/test.csv").exists() cleanup: new File("${FileUtils.TestDirectoryPath}/${FileUtils.InputPathPart}/test.csv").delete() } }
被测代码
该测试针对以下方法:
RequestBodyModel parseRequestEvent(APIGatewayProxyRequestEvent request) { byte[] bodyBytes = request.getBody().getBytes("UTF-8"); if (request.getIsBase64Encoded()) bodyBytes = Base64.getDecoder().decode(bodyBytes); RequestBodyModel model = new RequestBodyModel(); FileUpload.parse(bodyBytes, request.getHeaders().get('Content-Type')) .each { FileItem fileItem -> if (fileItem.getFieldName().equals("inputFile")) { File inputFile = FileUtils.CreateFileIfNotExists("${this.pathProvider.getBaseInputPath()}/${fileItem.getName()}"); fileItem.write(inputFile); model.inputFile = inputFile; return; } if (fileItem.getFieldName().equals("outputFileExtension")) { model.outputFileExtension = fileItem.getString(); return; } if (fileItem.getFieldName().equals("shouldExportDncRecords")) { model.shouldExportDncRecords = Boolean.valueOf(fileItem.getString()); return; } } return model; }
用到的模型类RequestBodyModel定义如下:
class RequestBodyModel { File inputFile; boolean shouldExportDncRecords; String outputFileExtension; }
测试结果
测试失败,目标文件未生成;调试发现FileUpload.parse()未返回任何FileItem。
使用的依赖库
delight-fileupload(基于Apache Commons FileUpload)- AWS Lambda Java Events
- Spock(单元测试框架)
核心问题
如何使用FileUpload或类似工具解析上述测试中的multipart/form-data请求,并正常获取FileItem进行处理?
内容的提问来源于stack exchange,提问作者Mike Warren
相关产品推荐
相关产品推荐

