I have 4 classes available, and I utilize 3 of them to create an instance of another class. This is how it's done:
const repo = new PaymentMessageRepository();
const gorepo = new GoMessageRepository();
const sqsm = new PaymentMessageQueueManager(process.env.SOME_ENV, process.env.ANOTHER_ENV);
const systemUnderTest = PaymentProcessorService(repo,gorepo,sqsm);
The test scenario I want to explore involves testing if, in the event that an Error is triggered by a method such as repo.methodOne()
, systemUnderTest
should return a specific response. To accomplish this, I need to mock the PaymentMessageRepository
class. How can I go about doing this?
All my classes are associated with Joi schema. I encountered challenges in this aspect but managed to resolve it using:
jest.mock('joi')
.
In addition, is it possible to apply mocking for only one particular test? Whenever I attempt to implement mocking, it seems like all my tests are affected by the mock. Should I separate them somehow?
Here is what I have implemented thus far:
import { PaymentMessageQueueManager } from '../Queues/PaymentMessageQueueManager';
import { PaymentMessageRepository, PaymentMessageRepository_Schema } from '../Repository/PaymentMessageRepository'
import { GoMessageRepository } from '../Services/GoMessageRepository';
import {PaymentProcessorService} from '../Services/PaymentProcessorService'
jest.mock('joi');
jest.mock('../Repository/PaymentMessageRepository', () => ({
PaymentMessageRepository : jest.fn().mockImplementation( () => ({
putItem: jest.fn(),
})),
PaymentMessageRepository_Schema: {
required : jest.fn(),
},
}));
jest.mock('../Services/GoMessageRepository', () => ({
GoMessageRepository: jest.fn().mockImplementation( () => ({
putItem: jest.fn(),
})),
GoMessageRepository_Schema: {
required: jest.fn(),
},
}));
jest.mock('../Queues/PaymentMessageQueueManager', () => ({
PaymentMessageQueueManager: jest.fn().mockImplementation( () => ({
sendToQ: jest.fn(),
})),
PaymentMessageQueueManager_Schema: {
required: jest.fn(),
}
}));
describe('PaymentProcessorService unit tests', () => {
const env = process.env
beforeEach(() => {
jest.resetModules()
process.env = { ...env }
});
test('When a dependency is null, processor service should not be created', () => {
process.env.PAYMENT_MESSAGE_TABLE_NAME = 'MOCK_TABLE_NAME';
const repo = new PaymentMessageRepository();
const gorepo = new GoMessageRepository();
const sqsm = new PaymentMessageQueueManager(process.env.SOME_ENV, process.env.ANOTHER_ENV);
expect ( () => new PaymentProcessorService(repo, undefined, sqsm)).toThrow(Error);
})
afterEach(() => {
process.env = env
});
test('When mocked dependencies, processor should return no error', () => {
const repo_mocked = new GoMessageRepository(); // <--- How to mock this so that repo_mocked.some_method() either throws or returns 0?
})
})
Currently, the issue I am facing is that the first test fails because when mocking 'Joi', it overrides the .assert()
method and alters its behavior, causing it to return a different result. As a result, even if there is a missing dependency, the overridden 'Joi' returns okay and causes the assertion to fail.
If I remove all mocks, the test functions as intended.
Am I approaching the mocking process incorrectly? My main goal is to be able to mock a specific method to return a certain response or trigger an exception, and then assert the outcome accordingly. Achieving this seamlessly in C# with XUnit is straightforward, but I find it challenging in TS/JS with Jest (my source files are in TypeScript while my test files are in JavaScript).