Mock 'S3' feature of 'aws-sdk' (nodeJS and Jest) - node.js

I need to test a file in charge of retrieving data from S3 through the 'aws-sdk' (nodeJs + Jest). The file is:
const AWS = require('aws-sdk');
let S3 = null;
const getS3 = async () => {
if (S3 === null) {
const config = {
endpoint: new AWS.Endpoint(process.env.S3_URL),
s3ForcePathStyle: true,
};
S3 = new AWS.S3(config);
}
return S3;
};
module.exports.getObjectList = async (prefix) => {
const params = {
Bucket: process.env.S3_BUCKET,
Delimiter: '/',
Prefix: prefix,
};
const s3 = await getS3();
const objectList = s3
.listObjects(params)
.promise()
.then((data) => {
const keys = data.Contents.map((c) => c.Key);
return keys;
})
.catch((err) => {
console.error(err);
return null;
});
return objectList;
};
and the test file is as below :
const s3Client = require('./s3Client');
const mockS3Instance = {
listObjects: jest.fn().mockReturnThis(),
promise: jest.fn().mockReturnThis(),
catch: jest.fn(),
};
jest.mock('aws-sdk', () => {
return {
S3: jest.fn(() => mockS3Instance),
Endpoint: jest.fn(() => {
'blabla';
}),
};
});
describe('s3Client tests', () => {
it('basic test', async () => {
const getObjectListResult = await s3Client.getObjectList('test');
expect(1).toBe(1);
});
});
But a error message is returned :
ypeError: s3.listObjects(...).promise(...).then is not a function

You need to add a then mock in your mockS3Instance object

Thanks to #gear4 reply, I was able to fix my code :
(main part is about the promise returned from the mock)
const s3Client = require('./s3Client');
const mockS3Instance = {
listObjects: jest.fn().mockReturnThis(),
promise: jest.fn(() => {
return new Promise((resolve, reject) => {
return resolve({
Contents: [{ Key: 'test-file-1' }, { Key: 'test-file-2' }],
});
});
}),
catch: jest.fn(),
};
jest.mock('aws-sdk', () => {
return {
S3: jest.fn(() => mockS3Instance),
Endpoint: jest.fn(() => {
'blabla';
}),
};
});
describe('s3Client tests', () => {
it('Dummy tests: to be implemented', async () => {
const getObjectListResult = await s3Client.getObjectList('test');
expect(JSON.stringify(getObjectListResult)).toBe(
JSON.stringify(['test-file-1', 'test-file-2']),
);
});
});

Related

Jest mock Knex transaction

I have the following lambda handler to unit test. It uses a library #org/aws-connection which has a function mysql.getIamConnection which simply returns a knex connection.
Edit: I have added the mysql.getIamConnection function to the bottom of the post
Edit: If possible, I'd like to do the testing with only Jest. That is unless it becomes to complicated
index.js
const {mysql} = require('#org/aws-connection');
exports.handler = async (event) => {
const connection = await mysql.getIamConnection()
let response = {
statusCode: 200,
body: {
message: 'Successful'
}
}
try {
for(const currentMessage of event.Records){
let records = JSON.parse(currentMessage.body);
await connection.transaction(async (trx) => {
await trx
.table('my_table')
.insert(records)
.then(() =>
console.log(`Records inserted into table ${table}`))
.catch((err) => {
console.log(err)
throw err
})
})
}
} catch (e) {
console.error('There was an error while processing', { errorMessage: e})
response = {
statusCode: 400,
body: e
}
} finally {
connection.destroy()
}
return response
}
I have written some unit tests and I'm able to mock the connection.transaction function but I'm having trouble with the trx.select.insert.then.catch functions. H
Here is my testing file
index.test.js
import { handler } from '../src';
const mocks = require('./mocks');
jest.mock('#org/aws-connection', () => ({
mysql: {
getIamConnection: jest.fn(() => ({
transaction: jest.fn(() => ({
table: jest.fn().mockReturnThis(),
insert: jest.fn().mockReturnThis()
})),
table: jest.fn().mockReturnThis(),
insert: jest.fn().mockReturnThis(),
destroy: jest.fn().mockReturnThis()
}))
}
}))
describe('handler', () => {
test('test handler', async () =>{
const response = await handler(mocks.eventSqs)
expect(response.statusCode).toEqual(200)
});
});
This test works partially but it does not cover the trx portion at all. These lines are uncovered
await trx
.table('my_table')
.insert(records)
.then(() =>
console.log(`Records inserted into table ${table}`))
.catch((err) => {
console.log(err)
throw err
})
How can set up my mock #org/aws-connection so that it covers the trx functions as well?
Edit:
mysql.getIamConnection
async function getIamConnection (secretId, dbname) {
const secret = await getSecret(secretId)
const token = await getToken(secret)
let knex
console.log(`Initialzing a connection to ${secret.proxyendpoint}:${secret.port}/${dbname} as ${secret.username}`)
knex = require('knex')(
{
client: 'mysql2',
connection: {
host: secret.proxyendpoint,
user: secret.username,
database: dbname,
port: secret.port,
ssl: 'Amazon RDS',
authPlugins: {
mysql_clear_password: () => () => Buffer.from(token + '\0')
},
connectionLimit: 1
}
}
)
return knex
}
Solution
#qaismakani's answer worked for me. I wrote it slightly differently but the callback was the key. For anyone interested here is my end solution
const mockTrx = {
table: jest.fn().mockReturnThis(),
insert: jest.fn().mockResolvedValue()
}
jest.mock('#org/aws-connection', () => ({
mysql: {
getIamConnection: jest.fn(() => ({
transaction: jest.fn((callback) => callback(mockTrx)),
destroy: jest.fn().mockReturnThis()
}))
}
}))
Updating your mock to look like this might do the trick:
const { mysql } = require("#org/aws-connection");
jest.mock("#org/aws-connection", () => ({
mySql: {
getIamConnection: jest.fn()
}
}));
const mockTrx = {
table: jest.fn().mockReturnThis(),
insert: jest.fn().mockResolveValue() // Resolve any data here
};
mysql.getIamConnection.mockReturnValue({
transaction: jest.fn((callback) => callback(mockTrx)),
});
You need to mock the transaction so that it executes your callback with a dummy trx. To do this, you need to make sure that all the functions inside the trx object return a reference back to it or a promise so that you can chain it appropriately.
Instead of mocking knex implementation, I've written knex-mock-client which allows you to mimic real db with an easy API.
Change your mock implementation with
import { handler } from "../src";
import { getTracker } from "knex-mock-client";
const mocks = require("./mocks");
jest.mock("#org/aws-connection", () => {
const knex = require("knex");
const { MockClient } = require("knex-mock-client");
return {
mysql: {
getIamConnection: () => knex({ client: MockClient }),
},
};
});
describe("handler", () => {
test("test handler", async () => {
const tracker = getTracker();
tracker.on.insert("my_table").responseOnce([23]); // setup's a mock response when inserting into my_table
const response = await handler(mocks.eventSqs);
expect(response.statusCode).toEqual(200);
});
});

How to mock AWS TimestreamWrite by jest

This project is to record data by AWS Timestream, and it works well.
However, I'm failed to mock AWS TimestreamWrite by using jest. I tried some ways but not working. Can someone help me?
My files as below:
ledger-service.js
const AWS = require("aws-sdk");
const enums = require("./enums");
var https = require("https");
var agent = new https.Agent({
maxSockets: 5000,
});
const tsClient = new AWS.TimestreamWrite({
maxRetries: 10,
httpOptions: {
timeout: 20000,
agent: agent,
},
});
module.exports = {
log: async function (audit) {
try {
if (Object.keys(audit).length !== 0) {
if (!isPresent(audit, "name")) {
throw new Error("Name shouldn't be empty");
}
if (!isPresent(audit, "value")) {
throw new Error("Value shouldn't be empty");
}
return await writeRecords(recordParams(audit));
} else {
throw new Error("Audit object is empty");
}
} catch (e) {
throw new Error(e);
}
},
};
function isPresent(obj, key) {
return obj[key] != undefined && obj[key] != null && obj[key] != "";
}
function recordParams(audit) {
const currentTime = Date.now().toString(); // Unix time in milliseconds
const dimensions = [
// { Name: "client", Value: audit["clientId"] },
{ Name: "user", Value: audit["userId"] },
{ Name: "entity", Value: audit["entity"] },
{ Name: "action", Value: audit["action"] },
{ Name: "info", Value: audit["info"] },
];
return {
Dimensions: dimensions,
MeasureName: audit["name"],
MeasureValue: audit["value"],
MeasureValueType: "VARCHAR",
Time: currentTime.toString(),
};
}
function writeRecords(records) {
try {
const params = {
DatabaseName: enums.AUDIT_DB,
TableName: enums.AUDIT_TABLE,
Records: [records],
};
return tsClient.writeRecords(params).promise();
} catch (e) {
throw new Error(e);
}
}
ledger-service.spec.js
const AWS = require("aws-sdk");
const audit = require("./ledger-service");
describe("ledger-service", () => {
beforeEach(async () => {
jest.resetModules();
});
afterEach(async () => {
jest.resetAllMocks();
});
it("It should write records when all success", async () => {
const mockAudit={
name: 'testName',
value: 'testValue',
userId: 'testUserId',
entity: 'testEntity',
action: 'testAction',
info: 'testInfo',
};
const mockWriteRecords = jest.fn(() =>{
console.log('mock success')
return { promise: ()=> Promise.resolve()}
});
const mockTsClient={
writeRecords: mockWriteRecords
}
jest.spyOn(AWS,'TimestreamWrite');
AWS.TimestreamWrite.mockImplementation(()=>mockTsClient);
//a=new AWS.TimestreamWrite();
//a.writeRecords(); //these two lines will pass the test and print "mock success"
await audit.log(mockAudit); //this line will show "ConfigError: Missing region in config"
expect(mockWriteRecords).toHaveBeenCalled();
});
});
I just think the the AWS I mocked doesn't pass into the ledger-service.js. Is there a way to fix that?
Thanks
updates: Taking hoangdv's suggestion
I am thinking jest.resetModules(); jest.resetAllMocks(); don't work. If I put the "It should write records when all success" as the first test, it will pass the test. However, it will fail if there is one before it.
Pass
it("It should write records when all success", async () => {
const mockAudit = {
name: 'testName',
value: 'testValue',
userId: 'testUserId',
entity: 'testEntity',
action: 'testAction',
info: 'testInfo',
};
await audit.log(mockAudit);
expect(AWS.TimestreamWrite).toHaveBeenCalledWith({
maxRetries: 10,
httpOptions: {
timeout: 20000,
agent: expect.any(Object),
},
});
expect(mockWriteRecords).toHaveBeenCalled();
});
it("It should throw error when audit is empty", async () => {
const mockAudit = {};
await expect(audit.log(mockAudit)).rejects.toThrow(`Audit object is empty`);
});
Failed
it("It should throw error when audit is empty", async () => {
const mockAudit = {};
await expect(audit.log(mockAudit)).rejects.toThrow(`Audit object is empty`);
});
it("It should write records when all success", async () => {
const mockAudit = {
name: 'testName',
value: 'testValue',
userId: 'testUserId',
entity: 'testEntity',
action: 'testAction',
info: 'testInfo',
};
await audit.log(mockAudit);
expect(AWS.TimestreamWrite).toHaveBeenCalledWith({
maxRetries: 10,
httpOptions: {
timeout: 20000,
agent: expect.any(Object),
},
});
expect(mockWriteRecords).toHaveBeenCalled();
});
In ledger-service.js you call new AWS.TimestreamWrite "before" module.exports, this means it will be called with actual logic instead of mock.
The solution is just mock AWS before you call require("./ledger-service");
ledger-service.spec.js
const AWS = require("aws-sdk");
describe("ledger-service", () => {
let audit;
let mockWriteRecords;
beforeEach(() => {
mockWriteRecords = jest.fn(() => {
return { promise: () => Promise.resolve() }
});
jest.spyOn(AWS, 'TimestreamWrite');
AWS.TimestreamWrite.mockImplementation(() => ({
writeRecords: mockWriteRecords
}));
audit = require("./ledger-service"); // this line
});
afterEach(() => {
jest.resetModules(); // reset module to update change for each require call
jest.resetAllMocks();
});
it("It should write records when all success", async () => {
const mockAudit = {
name: 'testName',
value: 'testValue',
userId: 'testUserId',
entity: 'testEntity',
action: 'testAction',
info: 'testInfo',
};
await audit.log(mockAudit);
expect(AWS.TimestreamWrite).toHaveBeenCalledWith({
maxRetries: 10,
httpOptions: {
timeout: 20000,
agent: expect.any(Object),
},
});
expect(mockWriteRecords).toHaveBeenCalled();
});
});

How to mock multer using jest/enzyme to file upload using axios post mock call

I am testing my express router with axios post-call to backend. I am getting 500 responses instead of 200, not sure how to mock the multer effectively.
Any thoughts on this? Thanks
routes.jsx
const axios = require('axios')
const router = express.Router()
const multer = require('multer')
const FormData = require('form-data')
const express = require('express')
const upload = multer({ storage: multer.memoryStorage() }).any()
router.post('/', upload, (req, res) => {
const formData = new FormData()
const { body } = req
req.files.forEach(file => {
formData.append(
'files',
file.buffer,
{
filename: file.originalname
},
file.originalname
)
})
axios
.post('/api/endpoint', formData)
.then(response => {return response
})
.catch(e => {
console.log(e)
})
})
module.exports = router
Below are my test case
routes.jsx.test
const axios = require('axios')
const MockAdapter = require('axios-mock-adapter')
const myroute = require('myroute')
const app = express()
const mock = new MockAdapter(axios)
const request = require('supertest')
const express = require('express')
const bodyParser = require('body-parser')
const multer = require('multer')
jest.mock('multer')
multer.mockImplementation(() => {
return {
any () {
return (req, res, next) => {
req.body = { userName: 'testUser' }
req.files = [
{
originalname: 'sample.name',
mimetype: 'sample.type',
path: 'sample.url'
}
]
return next()
}
}
}
})
app.use(bodyParser.json())
app.use('/', myroute)
describe('sendFiles', () => {
const url = '/api/endpoint'
test('200 response', () => {
const myMockRes = { mykey: 'myVal' }
let formData = new FormData()
const file = new Blob(['somee contents'], { type: 'multipart/form-data' })
formData.append('files', file)
formData.append('userName', 'testUser')
mock.onPost(url).reply(200, myMockRes)
return (
request(app)
.post('/')
.send({ userName: 'testUser', files: [file] })
//.expect('Content-Type', /json/)
.expect(200)
.then(response => {
const { data } = response.body
expect(data).toEqual(myMockRes)
})
)
})
})
error:
TypeError: Cannot read property 'any' of undefined in routes.jsx
const upload = multer({ storage: multer.memoryStorage() }).any()
When you use jest.mock('multer'), Jest automatically mocks the module and returns undefined when it gets called in the test. Since we want to mock memoryStorage and any methods as well, we have to do it explicitly by passing a factory as the second argument to jest.mock.
jest.mock('multer', () => {
const multer = () => ({
any: () => {
return (req, res, next) => {
req.body = { userName: 'testUser' }
req.files = [
{
originalname: 'sample.name',
mimetype: 'sample.type',
path: 'sample.url',
buffer: Buffer.from('whatever'), // this is required since `formData` needs access to the buffer
},
]
return next()
}
},
})
multer.memoryStorage = () => jest.fn()
return multer
})
The other issue is that Blob does not exist in Node. You can use Buffer.from to generate a buffer to send in the request.
const file = Buffer.from('whatever')
And you don't need to use FormData in the test.
The whole code:
// router.test.js
const axios = require('axios')
const MockAdapter = require('axios-mock-adapter')
const express = require('express')
const app = express()
const mock = new MockAdapter(axios)
const request = require('supertest')
const bodyParser = require('body-parser')
const myroute = require('./router')
jest.mock('multer', () => {
const multer = () => ({
any: () => {
return (req, res, next) => {
req.body = { userName: 'testUser' }
req.files = [
{
originalname: 'sample.name',
mimetype: 'sample.type',
path: 'sample.url',
buffer: Buffer.from('whatever'),
},
]
return next()
}
},
})
multer.memoryStorage = () => jest.fn()
return multer
})
app.use(bodyParser.json())
app.use('/', myroute)
describe('sendFiles', () => {
const url = '/api/endpoint'
test('200 response', () => {
const myMockRes = { mykey: 'myVal' }
const file = Buffer.from('whatever')
mock.onPost(url).reply(200, myMockRes)
return request(app)
.post('/')
.send({ userName: 'testUser', files: [file] })
.expect(200)
.then((response) => {
const { data } = response.body
expect(data).toEqual(myMockRes)
})
})
})
#Arun Kumar Mohan got me halfway there. Good happy path. But what about the error path? Arun has it right. You need to mock this. But what about triggering error paths within the callback? Providing a jest function that you can trigger can get you into those error paths.
import { UploadGuard } from '../../../src/guards';
import { Request } from 'express';
// Note: make a spy to get into the guts of the thing.
let spy = jest.fn();
jest.mock('multer', () => {
const multer = () => ({
any: () => {
return (req, res, next) => {
// Note: have the spy execute in the next.
return next(spy());
};
},
});
multer.memoryStorage = () => jest.fn();
return multer;
});
describe('Upload Guard', () => {
let guard: UploadGuard;
const loggerService = new MockLogger();
// Note: Good practice, always reset your mocks.
afterEach(() => jest.resetAllMocks());
beforeEach(() => {
spy = jest.fn();
guard = new UploadGuard(loggerService);
});
it('Should set the files on a request', async () => {
// Given
const executionContext = {
switchToHttp: () => ({
getRequest: () =>
({
headers: {
authorization: 'Bearer FakeJWT',
Content-Type: 'multipart/form-data',
},
body: {},
} as Request),
}),
};
// When
await guard.canActivate(executionContext as any);
// Then
expect(spy).toHaveBeenCalled();
});
it('Throw an error if something bad happens', async () => {
// Given
spy.mockImplementationOnce(() => {
// Note: Return not throw
return new Error('Bad Things');
});
const executionContext = {
switchToHttp: () => ({
getRequest: () => ({} as Request),
}),
};
try {
// When
await guard.canActivate(executionContext as any);
throw new Error('Should not happen');
} catch (err) {
// Then
expect(err.message).toBe('Bad Things');
}
});
});

Jest - resetting value in module and reloading import

I'm writing a test in jest for a module which uses a constant from a different module.
I want to set a different value for it for every test case, but I don't seem to be able to do so.
The test file:
import { Request, Response } from 'express';
const activityConsumer = require('../../src/utils/activity.consumer');
const mockRequest = {
params: {
activityArn: 'activityArn'
}
} as Request;
const mockedJsonFunction = jest.fn();
const mockResponse: any = {
json: jest.fn(),
status: jest.fn().mockReturnValue({ json: mockedJsonFunction }),
} as Response;
let stopConsumerMock;
describe('consumer handler', () => {
beforeAll(() => {
stopConsumerMock = activityConsumer.stopConsumer = jest.fn().mockReturnValue(1);
});
beforeEach(() => {
jest.resetModules();
});
afterEach(() => {
stopConsumerMock.mockClear();
mockResponse.json.mockClear();
});
describe('stopConsumingHandler', () => {
it('Should return success true and not call stopConsumer when no consumer exists', () => {
activityConsumer.consumer = undefined;
const { stopConsumingHandler } = require ('../../src/handlers/consumer.handlers');
stopConsumingHandler(mockRequest, mockResponse);
expect(stopConsumerMock.mock.calls.length).toEqual(0);
expect(mockResponse.json.mock.calls.length).toEqual(1);
expect(mockResponse.json).toHaveBeenCalledWith({ success: true });
});
it('Should return success true and call stopConsumer when consumer exists', () => {
activityConsumer.consumer = true;
const { stopConsumingHandler } = require ('../../src/handlers/consumer.handlers');
stopConsumingHandler(mockRequest, mockResponse);
expect(stopConsumerMock.mock.calls.length).toEqual(1);
expect(mockResponse.json.mock.calls.length).toEqual(1);
expect(mockResponse.json).toHaveBeenCalledWith({ success: true });
});
});
});
I want to replace the value of activityConsumer.consumer and then reload the consumer.handlers module but the re-assignment and reload does not seem to have any effect.
Please advise on how can I write this test properly.
Try this way, using jest.mock to modify import value of activityConsumer
import { Request, Response } from 'express';
// const activityConsumer = require('../../src/utils/activity.consumer');
const mockRequest = {
params: {
activityArn: 'activityArn'
}
} as Request;
const mockedJsonFunction = jest.fn();
const mockResponse: any = {
json: jest.fn(),
status: jest.fn().mockReturnValue({ json: mockedJsonFunction }),
} as Response;
let stopConsumerMock;
describe('consumer handler', () => {
beforeAll(() => {
// stopConsumerMock = activityConsumer.stopConsumer = jest.fn().mockReturnValue(1);
stopConsumerMock = jest.fn().mockReturnValue(1);
});
beforeEach(() => {
jest.resetModules(); // important line
});
afterEach(() => {
stopConsumerMock.mockClear();
mockResponse.json.mockClear();
});
describe('stopConsumingHandler', () => {
it('Should return success true and not call stopConsumer when no consumer exists', () => {
// activityConsumer.consumer = undefined;
// mock by this way
jest.mock('../../src/utils/activity.consumer', () => ({
consumer: undefined,
stopConsumer: stopConsumerMock,
}));
const { stopConsumingHandler } = require('../../src/handlers/consumer.handlers');
stopConsumingHandler(mockRequest, mockResponse);
expect(stopConsumerMock.mock.calls.length).toEqual(0);
expect(mockResponse.json.mock.calls.length).toEqual(1);
expect(mockResponse.json).toHaveBeenCalledWith({ success: true });
});
it('Should return success true and call stopConsumer when consumer exists', () => {
// activityConsumer.consumer = true;
// mock by this way
jest.mock('../../src/utils/activity.consumer', () => ({
consumer: true, // mock value for consumer
stopConsumer: stopConsumerMock,
}));
const { stopConsumingHandler } = require('../../src/handlers/consumer.handlers');
stopConsumingHandler(mockRequest, mockResponse);
expect(stopConsumerMock.mock.calls.length).toEqual(1);
expect(mockResponse.json.mock.calls.length).toEqual(1);
expect(mockResponse.json).toHaveBeenCalledWith({ success: true });
});
});
});

Spy function with params by Sinon.js

I'm trying to write some unit tests of code that uses typeorm without hitting the DB.
And I'm using sinon for spy/stub/mock.
This is my function.
async updateDoingToFailedWithLock(queryRunner: QueryRunner): Promise<void> {
await queryRunner.manager
.getRepository(Report)
.createQueryBuilder("report")
.useTransaction(true)
.setLock("pessimistic_write")
.update(Report)
.set({ status: ReportStatus.FAILED })
.where(`(status = "doing")`)
.execute();
}
I already wrote a fake test to make sure execute() is called by using spy function.
But I want to test the params of these functions createQueryBuilder..., the sure the params are correct.
I took a look at sinon document and it seems like sinon support test params by this API: spy().withArgs(arg1, arg2...).
But I'm not sure how to spy my function correctly.
describe("updateDoingToFailedWithLock()", (): void => {
let sandbox: Sinon.SinonSandbox;
beforeEach(() => (sandbox = Sinon.createSandbox()));
afterEach(() => sandbox.restore);
it("should be success", async (): Promise<void> => {
const fakeManager = {
getRepository: () => {
return fakeManager;
},
createQueryBuilder: () => {
return fakeManager;
},
useTransaction: () => {
return fakeManager;
},
setLock: () => {
return fakeManager;
},
update: () => {
return fakeManager;
},
set: () => {
return fakeManager;
},
where: () => {
return fakeManager;
},
execute: () => {},
};
const fakeQueryRunner = {
manager: fakeManager,
};
const connection = new typeorm.Connection({ type: "mysql" });
const reportService = new ReportService();
sandbox.stub(connection, "createQueryRunner").callsFake((): any => {
return fakeQueryRunner;
});
const queryRunner = connection.createQueryRunner();
const spy = sandbox.spy(fakeManager, "execute");
reportService.updateDoingToFailedWithLock(queryRunner);
expect(spy.calledOnce).be.true;
});
});
Any help is welcome. Thanks in advance!
I saw your code and there's something can be improved:
Use returnsThis() to replace return fakeManager
Don't forget await when calling updateDoingToFailedWithLock
describe("updateDoingToFailedWithLock()", (): void => {
let sandbox: sinon.SinonSandbox;
beforeEach(() => (sandbox = sinon.createSandbox()));
afterEach(() => sandbox.restore);
it("should be success", async (): Promise<void> => {
// using returnsThis()
const fakeManager = {
getRepository: sandbox.stub().returnsThis(),
createQueryBuilder: sandbox.stub().returnsThis(),
useTransaction: sandbox.stub().returnsThis(),
setLock: sandbox.stub().returnsThis(),
update: sandbox.stub().returnsThis(),
set: sandbox.stub().returnsThis(),
where: sandbox.stub().returnsThis(),
execute: sandbox.stub().returnsThis(),
}
const fakeQueryRunner = {
manager: fakeManager,
};
const reportService = new ReportService();
// having await here is important
await reportService.updateDoingToFailedWithLock(fakeQueryRunner);
expect(fakeManager.execute.calledOnce).to.be.true;
expect(fakeManager.createQueryBuilder.calledWith('report')).to.be.true;
});
});
Hope it helps

Resources