How do I mock AWS S3 GetObjectCommand with jest using the v3 sdk?

Viewed 3387

Testing an s3 upload? The method to test is

export class ProcessData {
  constructor() {}

  async process(): Promise<void> {
     const data = await s3Client.send(new GetObjectCommand(bucket));
     await parseCsvData(data.Body)
}

This is my attempt at the test case.

import {S3Client} from '@aws-sdk/client-s3';
jest.mock("aws-sdk/clients/s3", () => {
  return {
    S3Client: jest.fn(() => {
        send: jest.fn().mockImplementation(() => {
            data:  Buffer.from(require("fs").readFileSync(path.resolve(__dirname, "test.csv")));
        })
    })
  }
});

describe("@aws-sdk/client-s3 mock", () => {
  test('CSV Happy path', async () => {
    const processData = new ProcessData()
    await processData.process()
  }
}

The process gets to the parse method and throws an error "The bucket you are attempting to access must be addressed using the specific endpoint"

2 Answers

For anyone who wants to mock the client directly, you can use the library aws-sdk-client-mock which is recommended by the AWS SDK team.

Some introductory tutorial

The initial steps:

import fs from 'fs';

import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { mockClient } from 'aws-sdk-client-mock';

const mockS3Client = mockClient(S3Client);

And then you can mock it this way

mockS3Client.on(GetObjectCommand).resolves({
    Body: fs.createReadStream('path/to/some/file.csv'),
});

You can also spy on the client

const s3GetObjectStub = mockS3Client.commandcalls(GetObjectCommand)

// s3GetObjectStub[0] here refers to the first call of GetObjectCommand
expect(s3GetObjectStub[0].args[0].input).toEqual({
  Bucket: 'foo', 
  Key: 'path/to/file.csv'
});
Related