How to write unit test case for uploadFiles method using jest? - node.js

i am trying to write unit test case for uploadFiles() method. This method returns function so i have to check toHaveBeenCalledWith('files', 5). I have updated my test case below, I don't know how to mock return function upload.array. can anyone tell me is that possible?
Method
uploadFiles = (
storage: StorageType,
validationFn: (request: Request, file: Express.Multer.File, cb: FileFilterCallback) => Promise<void>,
) => {
// fileSize - size of an individual file (1024 * 1024 * 1 = 1mb)
const upload = multer({
storage: this[storage](),
limits: { fileSize: 1024 * 1024 * FILE_SIZE },
fileFilter: this.fileUtil.fileValidation(validationFn),
});
return upload.array("files", 5); // maximum files allowed to upload in a single request
};
Test Case
describe('FileService', () => {
// fileValidation Test suite
describe('fileValidation', () => {
let callbackFn: jest.Mock<any, any>;
let validationFn: jest.Mock<any, any>;
beforeEach(() => {
callbackFn = jest.fn();
validationFn = jest.fn();
});
afterEach(() => {
callbackFn.mockClear();
validationFn.mockClear();
});
it('should call the file filter method with image file types when request body has type image', async () => {
// Preparing
const request = {
body: {
entity_no: 'AEZ001',
type: 'image',
category: 'Shipping',
},
};
const file = {
originalname: 'some-name.png',
mimetype: 'image/png',
};
// Executing
const func = fileService.uploadFiles(StorageType.DISK, validationFn);
await func(request as Request, file as any, callbackFn);
});
});
});

You can use jest.mock(moduleName, factory, options) to mock multer module.
E.g.
fileService.ts:
import multer from 'multer';
const FILE_SIZE = 1;
type FileFilterCallback = any;
export enum StorageType {
DISK = 'disk',
}
export class FileService {
fileUtil = {
fileValidation(fn) {
return fn;
},
};
disk() {
return multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads');
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now());
},
});
}
uploadFiles = (
storage: StorageType,
validationFn: (request: Request, file: Express.Multer.File, cb: FileFilterCallback) => Promise<void>
) => {
const upload = multer({
storage: this[storage](),
limits: { fileSize: 1024 * 1024 * FILE_SIZE },
fileFilter: this.fileUtil.fileValidation(validationFn),
});
return upload.array('files', 5);
};
}
fileService.test.ts:
import { FileService, StorageType } from './fileService';
import multer from 'multer';
const mMulter = {
array: jest.fn(),
};
jest.mock('multer', () => {
const multer = jest.fn(() => mMulter);
const oMulter = jest.requireActual('multer');
for (let prop in oMulter) {
if (oMulter.hasOwnProperty(prop)) {
multer[prop] = oMulter[prop];
}
}
return multer;
});
describe('65317652', () => {
afterAll(() => {
jest.resetAllMocks();
});
let validationFn: jest.Mock<any, any>;
beforeEach(() => {
validationFn = jest.fn();
});
afterEach(() => {
validationFn.mockClear();
});
it('should pass', () => {
const fileService = new FileService();
fileService.uploadFiles(StorageType.DISK, validationFn);
expect(multer).toBeCalled();
expect(mMulter.array).toHaveBeenCalledWith('files', 5);
});
});
unit test result:
PASS examples/65317652/fileService.test.ts
65317652
✓ should pass (3 ms)
----------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------------|---------|----------|---------|---------|-------------------
All files | 84.62 | 100 | 71.43 | 84.62 |
fileService.ts | 84.62 | 100 | 71.43 | 84.62 | 19-22
----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.693 s

Related

"Missing region in config" after attempting to mock SecretsManager with Jest

I'm currently attempting to mock AWS SecretsManager for my unit testing with Jest, and everytime I'm hit with the ConfigError
My code is somewhat like this
//index.ts
import SM from "aws-sdk/clients/secretsmanager"
const secretManagerClient = new SM()
...
export const randomMethod = async (a: string, b: string) => {
let secret
const personalToken = {
SecretId: process.env.secretId,
}
secretManagerClient
.getSecretValue(personalToken, (err, data) => {
if (err) {
console.error(`[SECRETS MANAGER] Error fetching personal token : ${err}`)
} else if (data && data.SecretString) {
secret = data.SecretString
}
})
}
My mock goes like this :
//index.test.js
const mockGetSecretValue = jest.fn((SecretId) => {
switch (SecretId) {
case process.env.GITHUB_PERSONAL_TOKEN:
return {
SecretString: process.env.GITHUB_PERSONAL_TOKEN_VALUE,
}
default:
throw Error("secret not found")
}
})
jest.mock("aws-sdk/clients/secretsmanager", () => {
return jest.fn(() => {
return {
getSecretValue: jest.fn(({ SecretId }) => {
return mockGetSecretValue(SecretId)
}),
promise: jest.fn(),
}
})
})
However, I get this error thrown at me : ConfigError: Missing region in config, which I understand to some extent, however I don't understand why it occurs here in the mocking part...
Thanks in advance!
EDIT: Thanks to the 1st answer, I've managed to stop having this error. However, the getSecretValue() method is not returning the Secret value I want.
You should NOT use the callback of .getSecretValue() method with .promise() together. Just choose one of them. The error means you didn't mock the secretsmanager class correctly of aws-sdk.
E.g.
index.ts:
import SM from 'aws-sdk/clients/secretsmanager';
const secretManagerClient = new SM();
export const randomMethod = async () => {
const personalToken = {
SecretId: process.env.secretId || '',
};
try {
const data = await secretManagerClient.getSecretValue(personalToken).promise();
return data.SecretString;
} catch (err) {
console.error(`[SECRETS MANAGER] Error fetching personal token : ${err}`);
}
};
index.test.ts:
import { randomMethod } from '.';
import SM from 'aws-sdk/clients/secretsmanager';
import { mocked } from 'ts-jest/utils';
import { PromiseResult } from 'aws-sdk/lib/request';
jest.mock('aws-sdk/clients/secretsmanager', () => {
const mSecretManagerClient = {
getSecretValue: jest.fn().mockReturnThis(),
promise: jest.fn(),
};
return jest.fn(() => mSecretManagerClient);
});
describe('69977310', () => {
test('should get secret value', async () => {
process.env.secretId = 's1';
const mSecretManagerClient = mocked<InstanceType<typeof SM>>(new SM());
const mGetSecretValueRequest = mocked(mSecretManagerClient.getSecretValue());
mGetSecretValueRequest.promise.mockResolvedValue({
SecretString: JSON.stringify({ password: '123456' }),
} as PromiseResult<any, any>);
const actual = await randomMethod();
expect(actual).toEqual(JSON.stringify({ password: '123456' }));
expect(mSecretManagerClient.getSecretValue as jest.Mocked<any>).toBeCalledWith({ SecretId: 's1' });
});
test('should throw error', async () => {
process.env.secretId = 's1';
const logSpy = jest.spyOn(console, 'error').mockImplementation(() => 'suppress error log for testing');
const mSecretManagerClient = mocked<InstanceType<typeof SM>>(new SM());
const mGetSecretValueRequest = mocked(mSecretManagerClient.getSecretValue());
const mError = new Error('network');
mGetSecretValueRequest.promise.mockRejectedValue(mError);
await randomMethod();
expect(logSpy).toBeCalledWith(`[SECRETS MANAGER] Error fetching personal token : ${mError}`);
expect(mSecretManagerClient.getSecretValue as jest.Mocked<any>).toBeCalledWith({ SecretId: 's1' });
});
});
test result:
PASS examples/69977310/index.test.ts (7.722 s)
69977310
✓ should get secret value (4 ms)
✓ should throw error (1 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 50 | 100 | 100 |
index.ts | 100 | 50 | 100 | 100 | 6
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 8.282 s, estimated 10 s
package versions:
"aws-sdk": "^2.875.0",
"typescript": "^4.1.2",
"jest": "^26.6.3",
I've overlooked the fact that I was using a callback in order to bypass the promise().
The following is the correct code:
const mockGetSecretValue = jest.fn((SecretId, callback) => {
console.log("secretId", SecretId)
switch (SecretId) {
case process.env.GITHUB_PERSONAL_TOKEN:
const data = {
SecretString: process.env.GITHUB_PERSONAL_TOKEN_VALUE,
}
callback(null, data)
break;
default:
const err = new Error("secret not found")
throw err
}
})
jest.mock("aws-sdk/clients/secretsmanager", () => {
return jest.fn(() => {
return {
promise: jest.fn(),
getSecretValue: jest.fn(({ SecretId }, callback) => {
return mockGetSecretValue(SecretId, callback)
}),
}
})
})
Thanks again for your help #slideshowp2!

How to mock async method with jest in nodejs

I have below mentioned files
|_ utils.js
|_methods.js
I am doing unit testing for rest.js methods, file contents are
methods.js
import Express from 'express'
import { add_rec } from './utils'
export const create_rec = () => async (req: Express.Request, res: Express.Response) => {
const rec_body = req.body.rec
return add_rec(rec_body)
.then((ret) => res.status(201).send(ret))
.catch((e) => {
res.status(500).send({ message: e.message })
})
}
How can mock the add_rec async function so that I can unit-test my create_rec
function
I am trying to test create_rec below way but it is not allowing me to mock add_rec method
mport { getMockReq, getMockRes } from '#jest-mock/express'
import { add_rec } from './utils'
jest.mock('./utils')
describe('test create_rec method valid param', () => {
it('test create_rec method', async () => {
const req = getMockReq({
body: {
rec: {},
},
})
const { res } = getMockRes<any>({
status: jest.fn(),
send: jest.fn(),
})
add_rec.mockResolved({}) // this line is giving error in fact it is not mocked i think
await create_rec()(req, res)
expect(res.status).toHaveBeenCalledTimes(1)
expect(res.send).toHaveBeenCalledTimes(1)
})
})
Please help me with this.
Your code is almost correct, except that you need to do some processing on the TS type of the mock method, you can use type assertion.
E.g.
methods.ts:
import Express from 'express';
import { add_rec } from './utils';
export const create_rec = () => async (req: Express.Request, res: Express.Response) => {
const rec_body = req.body.rec;
return add_rec(rec_body)
.then((ret) => res.status(201).send(ret))
.catch((e) => {
res.status(500).send({ message: e.message });
});
};
utils.ts:
export async function add_rec(params): Promise<any> {
console.log('real implementation');
}
methods.test.ts:
import Express from 'express';
import { create_rec } from './methods';
import { add_rec } from './utils';
jest.mock('./utils');
describe('68419899', () => {
test('should pass', async () => {
(add_rec as jest.MockedFunction<any>).mockResolvedValueOnce({});
const req = ({ body: { rec: {} } } as unknown) as Express.Request;
const res = ({ status: jest.fn().mockReturnThis(), send: jest.fn() } as unknown) as Express.Response;
await create_rec()(req, res);
expect(add_rec).toBeCalledWith({});
expect(res.status).toBeCalledWith(201);
expect(res.send).toBeCalledWith({});
});
});
test result:
PASS examples/68419899/methods.test.ts (8.659 s)
68419899
✓ should pass (5 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 81.82 | 100 | 66.67 | 75 |
methods.ts | 88.89 | 100 | 80 | 83.33 | 10
utils.ts | 50 | 100 | 0 | 50 | 2
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.198 s

Jest unit test on('error') of createWriteStream

I am using Nestjs and have written the function below which recieves a file from a post request and saves it in a folder in my project.
My issue is I'm not sure how to test the on('error') branch.
function to unit test.
saveFile({ createReadStream, filename }: FileUpload): Promise<boolean> {
return new Promise(async (resolve, reject) => {
createReadStream().pipe(
createWriteStream(join(process.cwd(), `apps/mull-api/uploads/${filename}`))
.on('finish', () => resolve(true))
.on('error', () => {
console.log(createReadStream);
reject(false);
})
);
});
}
How I am testing the on('finish') branch
it('should save file', async () => {
const returnedFile = await service.saveFile(mockFile);
expect(returnedFile).toBe(true);
});
This is what my mockFile looks like. I tried providing a mockFile with empty name and it errors out.
export const mockFile: FileUpload = {
filename: 'zoro',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream(): ReadStream {
return fs.createReadStream(join(process.cwd(), `apps/mull-api/uploads/mock-upload/zoro`));
},
};
We can mock createWriteStream, .on('finish') and .on('error') methods using mockImplementation(). And trigger these two events in the mock implementation function by ourself.
The 'finish' event handler in the mock implementation function is () => resolve(true); The 'error' event handler in the mock implementation function is () => reject(false);
See Mock Implementations, and below example:
const myMockFn = jest.fn(cb => cb(null, true));
myMockFn((err, val) => console.log(val));
// > true
index.ts:
import { createWriteStream, ReadStream } from 'fs';
import { join } from 'path';
export interface FileUpload {
filename: string;
mimetype: string;
encoding: string;
createReadStream(): ReadStream;
}
export class FileService {
public saveFile({ createReadStream, filename }: FileUpload): Promise<boolean> {
return new Promise(async (resolve, reject) => {
createReadStream().pipe(
createWriteStream(join(process.cwd(), `apps/mull-api/uploads/${filename}`))
.on('finish', () => resolve(true))
.on('error', () => {
reject(false);
}),
);
});
}
}
index.test.ts:
import { FileService, FileUpload } from './';
import { createWriteStream, WriteStream } from 'fs';
import { mocked } from 'ts-jest/utils';
jest.mock('fs');
describe('64485251', () => {
afterAll(() => {
jest.resetAllMocks();
jest.clearAllMocks();
});
it('should save file', async () => {
const mockReadStream = { pipe: jest.fn() };
const mockFile: FileUpload = {
filename: 'zoro',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: jest.fn().mockReturnValueOnce(mockReadStream),
};
const mockWriteStream = {
on: jest.fn().mockImplementation(function(this, event, handler) {
if (event === 'finish') {
handler();
}
return this;
}),
};
mocked(createWriteStream).mockReturnValueOnce((mockWriteStream as unknown) as WriteStream);
const service = new FileService();
const actual = await service.saveFile(mockFile);
expect(mockFile.createReadStream).toBeCalledTimes(1);
expect(mockReadStream.pipe).toBeCalledTimes(1);
expect(createWriteStream).toBeCalledWith(expect.stringContaining('apps/mull-api/uploads/zoro'));
expect(mockWriteStream.on).toBeCalledWith('finish', expect.any(Function));
expect(mockWriteStream.on).toBeCalledWith('error', expect.any(Function));
expect(actual).toBeTruthy();
});
it('should handle error if save file failed', async () => {
const mockReadStream = { pipe: jest.fn() };
const mockFile: FileUpload = {
filename: 'zoro',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: jest.fn().mockReturnValueOnce(mockReadStream),
};
const mockWriteStream = {
on: jest.fn().mockImplementation(function(this, event, handler) {
if (event === 'error') {
handler();
}
return this;
}),
};
mocked(createWriteStream).mockReturnValueOnce((mockWriteStream as unknown) as WriteStream);
const service = new FileService();
await expect(service.saveFile(mockFile)).rejects.toEqual(false);
expect(mockFile.createReadStream).toBeCalledTimes(1);
expect(mockReadStream.pipe).toBeCalledTimes(1);
expect(createWriteStream).toBeCalledWith(expect.stringContaining('apps/mull-api/uploads/zoro'));
expect(mockWriteStream.on).toBeCalledWith('finish', expect.any(Function));
expect(mockWriteStream.on).toBeCalledWith('error', expect.any(Function));
});
});
unit test result:
PASS src/stackoverflow/64485251/index.test.ts (10.201s)
64485251
✓ should save file (6ms)
✓ should handle error if save file failed (3ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 11.344s

How does one properly to unit test Joi Schemas validation?

I created a Joi validation schema that gets called in my routes. However when I run a code coverage that file is NOT being covered. So, I am trying to write a test for it.
Validator.js
const Joi = require('joi');
module.exports = {
validateExternalId: (schema, name) => {
return (req, res, next) => {
const result = Joi.validate({ param: req.params[name] }, schema);
if (result.error) {
return res.status(400).send(result.error.details[0].message);
}
next();
};
},
schemas: {
idSchema: Joi.object().keys({
param: Joi.string().regex(/^[a-zA-Z0-9]{20}$/).required()
})
}
};
Validator.test.js
const { validateExternalId, schemas } = require('../../src/helpers/validation');
const app = require('../../src/router')
const mockResponse = () => {
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
return res;
};
describe('Testing validateExternalId schema', () => {
it('It can validate the external Id Regex length', done => {
const req = {
params: [
{
extClientId: 'abcdefghij0123456789'
}
]
};
app.use('/token/:extClientId', validateExternalId(schemas.idSchema, 'extClientId');
// expect().toHaveBeenCalled();
});
});
Please Go Easy on ME... Here is my attempt on testing this Joi validator. I tried to but my expected wasn't working so I commented it out for now. any pointers would be appreciated. thank you
Here is the unit test solution:
validator.js:
const Joi = require('joi');
module.exports = {
validateExternalId: (schema, name) => {
return (req, res, next) => {
const result = Joi.validate({ param: req.params[name] }, schema);
if (result.error) {
return res.status(400).send(result.error.details[0].message);
}
next();
};
},
schemas: {
idSchema: Joi.object().keys({
param: Joi.string()
.regex(/^[a-zA-Z0-9]{20}$/)
.required(),
}),
},
};
validator.test.js:
const { validateExternalId, schemas } = require('./validator');
const Joi = require('joi');
describe('60730701', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should send error', () => {
const validationResults = { error: { details: [{ message: 'validation error' }] } };
const validateSpy = jest.spyOn(Joi, 'validate').mockReturnValueOnce(validationResults);
const mReq = { params: { extClientId: '123' } };
const mRes = { status: jest.fn().mockReturnThis(), send: jest.fn() };
validateExternalId(schemas.idSchema, 'extClientId')(mReq, mRes);
expect(validateSpy).toBeCalledWith({ param: '123' }, schemas.idSchema);
expect(mRes.status).toBeCalledWith(400);
expect(mRes.send).toBeCalledWith('validation error');
});
it('should pass the validation and call api', () => {
const validationResults = { error: undefined };
const validateSpy = jest.spyOn(Joi, 'validate').mockReturnValueOnce(validationResults);
const mReq = { params: { extClientId: '123' } };
const mRes = {};
const mNext = jest.fn();
validateExternalId(schemas.idSchema, 'extClientId')(mReq, mRes, mNext);
expect(validateSpy).toBeCalledWith({ param: '123' }, schemas.idSchema);
expect(mNext).toBeCalled();
});
});
unit test results with 100% coverage:
PASS stackoverflow/60730701/validator.test.js (9.96s)
60730701
✓ should send error (6ms)
✓ should pass the validation and call api (2ms)
--------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
validator.js | 100 | 100 | 100 | 100 |
--------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 11.647s, estimated 15s
source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60730701

Jest mock typescript dependency

My index.ts file looks like this
import {IS3Client, S3Client} from './client/S3Client';
const s3: IS3Client = new S3Client();
export async function someFunc(event: any, context: any, callback: any) {
const x: string = await s3.getFile('a','b');
}
S3Client.ts looks like this
import * as AWS from 'aws-sdk';
export interface IS3Client {
getFile(bucketName: string, fileName: string): Promise<any>;
}
export class S3Client implements IS3Client {
private s3Client: AWS.S3;
constructor() {
this.s3Client = new AWS.S3();
}
public async getFile(bucketName: string, fileName: string): Promise<any> {
const params = {
Bucket: bucketName,
Key: fileName,
};
return (await this.s3Client.getObject(params).promise()).Body.toString();
}
}
Now I am interested to mock the getFile function to return what I want when I am testing index.ts
My test case looks like this
import {someFunc} from '../src/index';
import { S3Client } from '../src/client/S3Client';
describe("Test Suite", () => {
beforeAll(()=>{
jest.mock('../src/client/S3Client');
const mockedClient: jest.Mocked<S3Client> = new S3Client() as any;
mockedClient.getFile.mockImplementation(() => Promise.resolve('hello'));
});
it("testCase", () => {
const req = {
"key" : ["value"]
};
someFunc(req, null, null);
})
});
I am getting the following error :
TypeError: mockedClient.getFile.mockImplementation is not a function
Somehow this is looking much harder than I thought. Can someone suggest something, Thanks in advance ?
I added another class like this
import { SecretsManager } from 'aws-sdk';
export default class XUtils {
private secretsManager: SecretsManager;
constructor(secretsManager: SecretsManager) {
this.secretsManager = secretsManager;
}
public async getData(urlPrefix: string): Promise<any[]> {
return ['data'];
}
}
And my index.ts looks something like this :
import {IS3Client, S3Client} from './client/S3Client';
import XUtils from './utils/XUtils';
import { SecretsManager } from 'aws-sdk';
const s3: IS3Client = new S3Client();
const secretsManager: SecretsManager = new SecretsManager({ region: process.env.AWS_REGION });
const xUtils: XUtils = new XUtils(secretsManager)
export async function someFunc(event: any, context: any, callback: any) {
const x: string = await s3.getFile('a','b');
const y = await xUtils.getData(x);
}
Following from what you suggested, I modified my test case to something like this :
import {someFunc} from '../src/index';
import { S3Client } from '../src/client/S3Client';
import XUtils from '../utils/XUtils';
jest.mock('../src/client/S3Client', () => {
const mS3Client = { getFile: jest.fn() };
return { S3Client: jest.fn(() => mS3Client) };
});
jest.mock('../utils/XUtils', () => {
const mXUtils = { getData: jest.fn() };
return { XUtils: jest.fn(() => mXUtils) };
});
describe("Test Suite", () => {
beforeAll(()=>{
mockedClient = new S3Client() as any;
mockedClient.getFile.mockImplementation(() => Promise.resolve('url'));
mockedXUtils = new XUtils(null) as any;
mockedXUtils.getData.mockImplementation(() => Promise.resolve(['data']))
});
it("testCase", () => {
const req = {
"key" : ["value"]
};
someFunc(req, null, null);
})
});
I am getting error now as
TypeError: XUtils_1.default is not a constructor
What exactly is this problem ?
You can't use jest.mock in the function scope. It should be used in module scope.
You should use async/await for someFunc method in your test case.
E.g.
index.ts:
import { IS3Client, S3Client } from './s3client';
const s3: IS3Client = new S3Client();
export async function someFunc(event: any, context: any, callback: any) {
const x: string = await s3.getFile('a', 'b');
}
s3client.ts:
import * as AWS from 'aws-sdk';
export interface IS3Client {
getFile(bucketName: string, fileName: string): Promise<any>;
}
export class S3Client implements IS3Client {
private s3Client: AWS.S3;
constructor() {
this.s3Client = new AWS.S3();
}
public async getFile(bucketName: string, fileName: string): Promise<any> {
const params = {
Bucket: bucketName,
Key: fileName,
};
return (await this.s3Client.getObject(params).promise()).Body!.toString();
}
}
index.test.ts:
import { someFunc } from './';
import { S3Client } from './s3client';
jest.mock('./s3client', () => {
const mS3Client = { getFile: jest.fn() };
return { S3Client: jest.fn(() => mS3Client) };
});
describe('Test Suite', () => {
let mockedClient: jest.Mocked<S3Client>;
beforeAll(() => {
mockedClient = new S3Client() as any;
mockedClient.getFile.mockImplementation(() => Promise.resolve('hello'));
});
it('testCase', async () => {
const req = {
key: ['value'],
};
await someFunc(req, null, null);
expect(mockedClient.getFile).toBeCalledWith('a', 'b');
});
});
Unit test results with 100% coverage:
PASS stackoverflow/60445082/index.test.ts (8.548s)
Test Suite
✓ testCase (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.04s
source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60445082

Resources