jest.mockImplementation()-콜백함수 Mocking
BACKEND
NESTJS
jest.mockImplementation()
jest.mockImplementation(fn)은 Jest에서 Mock 함수의 동작을 커스텀하게 정의하는 데 사용되는 메서드입니다. 즉, jest.fn()으로 생성한 Mock 함수가 호출될 때 어떤 로직을 실행할지 직접 지정할 수 있습니다.
const mockFunction = jest.fn().mockImplementation((name) => `Hello, ${name}!`);
console.log(mockFunction("John")); // "Hello, John!"
console.log(mockFunction("Jane")); // "Hello, Jane!"
위 간단한 예제를 설명하자면,
jest.fn()으로 Mock 함수를 만들고, mockImplementation()을 사용하여 동작을 정의합니다.
함수가 호출될 때 전달된 name을 활용하여 "Hello, ${name}!"를 반환하도록 지정합니다.
그렇다면 실전 예제의 경우에 어떤 사용 케이스가 있는지 알아볼게요.
콜백 함수
특정 함수가 콜백함수를 실행하는 경우, mockImplementation()
를 활용할 수 있습니다.
다음은 transaction을 중앙화하여 사용하기 위한 코드입니다.
runInTransaction
메서드는 transaction을 실행할 콜백함수을 전달받아 실행하죠.
import { DataSource } from "typeorm";
import { TransactionManagerPort } from "../port/transaction-manager.port";
export class TypeormTransactionAdapter
implements TransactionManagerPort
{
constructor(private readonly dataSource: DataSource) {
if (!this.dataSource) {
throw new Error(
"DataSource is not provided to TypeormTransactionAdapter!",
);
}
}
async runInTransaction<T>(
fn: () => Promise<T>,
): Promise<T> {
const qr = this.dataSource.createQueryRunner();
await qr.connect();
await qr.startTransaction();
try {
const result = await fn();
await qr.commitTransaction();
await qr.release();
return result;
} catch (e) {
await qr.rollbackTransaction();
await qr.release();
throw e;
}
}
}
runInTransaction
메서드를 Mocking하기 위해서는 다음과 같이 jest.fn()만으로는 Mocking 할 수 없습니다.
❌
describe("UpdateTechUseCase", () => {
let transactionManager: jest.Mocked<TransactionManagerPort>;
transactionManager = {
runInTransaction: jest
.fn()
};
runInTransaction
은 콜백 함수를 실행해야하여 반환하여야하기 때문이죠.
따라서 이 경우에 mockImplementation
을 통해 비동기 콜백함수를 실행하여 반환한다를 작성해주면 됩니다.
🅾️
let transactionManager: jest.Mocked<TransactionManagerPort>;
beforeEach(async () => {
transactionManager = {
runInTransaction: jest
.fn()
.mockImplementation(async (fn) => await fn()),
};
위와 같이 콜백함수를 실행하는 메서드가 있다면 mockImplementation
을 활용하면 되겠습니다.