I am using S3 Select to query the CSV file and extract the rows out of it in my nodejs application. How to write a unit test to mock the response of the SelectObjectContentCommand
.
The response is of type SelectObjectContentCommandOutput
import { SelectObjectContentCommand, S3Client, ExpressionType, FileHeaderInfo } from '@aws-sdk/client-s3';
const s3Client = new S3Client({});
export const getDataUsingS3Select = async (bucketName: string, fileName: string, query: string, params: any) => {
const command = new SelectObjectContentCommand(params);
const response = await s3Client.send(command);
if (response.$metadata.httpStatusCode === 200) {
if (response.Payload) {
const data = convertDataToJson(response.Payload);
return data;
} else {
console.log(`S3Select did not have payload for ${bucketName}/${fileName}`);
return [];
}
} else {
console.log(`S3Select did not receive 200 for ${bucketName}/${fileName}.
Metadata is ${response.$metadata}`);
return [];
}
}
I got this working by using the Symbol.asyncIterator property:
class MockAsyncIterator {
constructor(readonly chunks: string[]) {
}
async* [Symbol.asyncIterator]() {
for (const c of this.chunks) {
yield { Records: { Payload: Buffer.from(c, "utf8") } }
}
}
}
then, using aws-sdk-client-mock we can test your function like so:
import { mockClient } from "aws-sdk-client-mock";
const s3Mock = mockClient(S3Client);
test("s3 query", async () => {
s3Mock.on(SelectObjectContentCommand).resolves({
Payload: new MockAsyncIterator(["column1,column2", "value1,value2"]),
"$metadata": {
httpStatusCode: 200
}
})
const query = {
// query params
};
const result = await getDataUsingS3Select("my-bucket", "my.csv", "SELECT * FROM S3Object", query);
expect(result).toBeDefined();
// additional checks
});