How to mock the aws-sdk?
Tags: jest, test, node, awssdk
Published: 2021-09-09 17:19:02

# Class to be tested
```typescript
import { Lambda } from 'aws-sdk';

export default class Service {
    public async callLambda(): Promise<void> {
        const lambda = new Lambda();
        const params: Lambda.Types.InvocationRequest = {
            FunctionName: `function-name`,
            InvocationType: 'Event',
        };
        await lambda.invoke(params).promise();
    }
}
```
- Let suppose that we have a service that call a lambda using the `aws-sdk` library.
- `aws-sdk` version: `2.546.0`.

# Unit test with the mock
## First way
```typescript
import Service from '../../../../src/api/services/Service';

const fakePromise = {
    promise: jest.fn(),
};

jest.mock('aws-sdk', () => ({
    Lambda: jest.fn(() => ({
        invoke: () => fakePromise,
    })),
}));

describe('callLambda', () => {

    it('should return something... ', async done => {
        const service = new Service();
        const result = await service.callLambda();
        expect(result).toBeUndefined();
        done();
    });

    it('should throw an error... ', async done => {
        // modifying the implementation before call the function
        fakePromise.promise = jest.fn()
            .mockImplementation(() => Promise.reject(new Error()));

        try {
            const service = new Service();
            const result = await service.callLambda();
            expect(result).toBeUndefined();
        } catch (error) {
            expect(error).toBeDefined();
        }
        done();
    });
});
```
## Second way
```typescript
import { Lambda } from 'aws-sdk';
import Service from '../../../../src/api/services/Service';

// removing the factory function of the first way
jest.mock('aws-sdk');

describe('callLambda', () => {
    // moving the fake to inside our describe test
    // because we don't need it in jest.mock
    const fakePromise = {
        promise: jest.fn(),
    };

    beforeEach(() => {
        // adding the implementation before each test
        (Lambda as any).mockImplementation(() => {
            return {
                invoke: () => fakePromise,
            };
        });
    });

    it('should return something... ', async done => {
        const service = new Service();
        const result = await service.callLambda();
        expect(result).toBeUndefined();
        done();
    });

    it('should throw an error... ', async done => {
        // modifying the implementation before call the function
        fakePromise.promise = jest.fn()
            .mockImplementation(() => Promise.reject(new Error()));

        try {
            const service = new Service();
            const result = await service.callLambda();
            expect(result).toBeUndefined();
        } catch (error) {
            expect(error).toBeDefined();
        }
        done();
    });
});
```
- Inside the unit tests we can just change the `fakePromise` or update the `mockImplementation` to pretend the behaviors that we need.
- We can use these approaches to create unit test for other classes inside the `aws-sdk`.
- `jest` version: `24.9.0`.

# Conclusion
The most difficult part of writing unit test is creating the mocks for external libraries, the purpose of this article is just help someone with troubles to mock this kind of library. We have a lot of ways to mock libraries, feel free to comment and send suggestions.