Reputation: 4342
I've tried many methods i've found on the internet about mocking aws-sdk services but none of them worked for me, i've even tried the module aws-sdk-mock
but that doesn't work and i think that's because i am not making use of the aws-sdk
in a function handler.
I am using jest
as my test runner and assertion, so the code i have now is like this:
test.js
const aws = require('aws-sdk-mock');
const Admin = require('./../../../serverless/entities/Admin');
describe('Entity - Admin test', () => {
jest.spyOn(aws.CognitoIdentityServiceProvider.prototype, 'listUsersInGroup', () => {
return {
promise: Promise.resolve({ foo: 'bar' })
};
});
const data = Admin.getListOfUsers();
console.log(data);
});
Admin.js
/**
* Admin entity class
* This class should help managing all super user actions that are required for the sportstracker's application
* Amazon services used by this entity:
* - Cognito (User Pool)
* Required IAM Policy actions:
* - cognito-idp:ListUsersInGroup
* - cognito-idp:ListUsers
* - cognito-idp:AdminCreateUser
* - cognito-idp:AdminDeleteUser
* - cognito-idp:AdminGetUser
* - cognito-idp:AdminListGroupsForUser
* - cognito-idp:AdminUpdateUserAttributes
* - cognito-idp:AdminRemoveUserFromGroup
*/
const aws = require('aws-sdk');
const User = require('./../lib/User');
const cognito = new aws.CognitoIdentityServiceProvider();
const UserPoolId = process.env['COGNITO_USER_POOL_ID'];
const rolesMap = {
admin: 'SuperUser',
member: 'Member'
};
/**
* @typedef UsersList
* @property {Array<UserObject>} members - The list of members
* @property {Array<UserObject>} admins - The list of admins
*/
class Admin {
/**
* Gets a list of users for both admin and members.
* This executes 2 methods for aws.cognito [admin, member]
* @returns {Promise<UsersList>} - The object containing the list of members and admins
*/
static async getListOfUsers () {
const operations = [
cognito.listUsersInGroup({ UserPoolId, GroupName: rolesMap.admin }).promise(),
cognito.listUsersInGroup({ UserPoolId, GroupName: rolesMap.member }).promise()
];
const results = await Promise.all(operations);
return {
admins: results[0].Users.map(user => User.mapUserData(user)),
members: results[1].Users.map(user => User.mapUserData(user))
};
}
...
}
module.exports = Admin;
the error i get for this code is:
TypeError: Cannot read property 'prototype' of undefined
this is because the prototype of all services in the sdk have no defined methods until the constructor is called, and i see why they created a module like aws-sdk-mock
but even that module did not help me, so how can i make a proper way to mock the aws services in a non-function lambda handler?
Upvotes: 3
Views: 2812
Reputation: 11
This one works for me
const AWS = require('aws-sdk');
jest.mock('aws-sdk');
AWS.CognitoIdentityServiceProvider.prototype.listUsers = jest.fn().mockReturnValue({
promise: jest.fn().mockResolvedValue({})
});
Upvotes: 1
Reputation: 16037
To mock a third-party package in jest
, you can create a __mocks__
directory in the same level as your node_modules
that will contain your mocked functions.
For example,
.
├── README.md
├── __mocks__
└── aws-sdk.js
├── jest.config.js
├── node_modules
├── package.json
├── src
└── yarn.lock
Your aws-sdk.js
mock file can contain the following:
module.exports.CognitoIdentityServiceProvider = jest.fn(() => ({
listUsersInGroup: mockListUsersInGroup,
}))
const mockListUsersInGroup = jest.fn((params) => ({
// You can replace the resolved value.
promise: () => Promise.resolve({}),
}))
Upvotes: 2