如何使用 Jest 监控 ES6 方法调用?
How to use Jest to monitor ES6 method calls?
正在使用打字稿测试调用实用程序 class 的 class。目标是模拟实用程序 class 并测试传递给调用的数据。
一个class待测试
import {Utils} from "~/src/play/utils";
export class Actions {
constructor() {
}
async readFile(): Promise<void> {
const utils = new Utils();
await utils.action(5)
}
}
const actions = new Actions();
actions.readFile()
实用程序class
export class Utils {
constructor() {}
async action(count: number): Promise<boolean> {
console.log(count);
return Promise.resolve(true);
}
}
测试脚本
// @ts-ignore
import {Utils} from "./utils";
import {Actions} from "~/src/play/actions";
const mockUtils = jest.fn();
jest.mock('../utils', () => {
return {
Utils: jest.fn().mockImplementation(() => {
return {
default: () => {return {utils: mockUtils}},
action: () => {
return 5;
}
}
})
}
})
describe('actions', () => {
beforeEach(() => {
// Utils.mockClear();
mockUtils.mockClear();
})
test('success', async () => {
const actions = new Actions()
await actions.readFile()
expect(mockUtils).toHaveBeenCalledWith(2)
})
})
它似乎没有接受模拟。结果是
Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: 2
Number of calls: 0
at Object.<anonymous> (/Users/jrobens/NetBeansProjects/azuron/winpay-uploader/src/play/__test__/actions.spec.ts:28:27)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
采纳@Stanislav Šolc 的建议添加 return 和参数值,包括 async
// @ts-ignore
import {Utils} from "../utils";
import {Actions} from "../actions";
const mockUtils = jest.fn();
jest.mock('../utils', () => {
return {
Utils: jest.fn().mockImplementation(() => {
return {
default: () => {return {utils: mockUtils}},
action: (count: number): Promise<boolean> => {
console.log(count);
return Promise.resolve(true);
}
}
})
}
})
结果不变
jest.mock() 中的模块路径必须与用于在测试单元中加载依赖项的路径完全相同。顺便说一句,这就是测试与测试单元位于同一目录中的原因(您可能不会这样做)。
并且您必须模拟模块的确切结构,当然还有方法的异步性质。因此,在您的情况下,您使用异步操作方法导出构造函数。所以这样的事情是更好的开始。
jest.mock('~/src/play/utils', () => {
return {
Utils: jest.fn().mockImplementation(() => {
return {action: jest.fn().mockResolvedValue(5)};
}
}
});
您可以使用 jest.spyOn(object, methodName) to mock Utils.prototype.action()
method. Use jest.restoreAllMocks() 将所有模拟恢复到 afterEach
挂钩中的原始值。防止mock的值影响其他测试用例。
例如
actions.ts
:
import { Utils } from './utils';
export class Actions {
constructor() {}
async readFile(): Promise<void> {
const utils = new Utils();
await utils.action(5);
}
}
utils.ts
:
export class Utils {
constructor() {}
async action(count: number): Promise<boolean> {
console.log(count);
return Promise.resolve(true);
}
}
actions.test.ts
:
import { Utils } from './utils';
import { Actions } from './actions';
describe('actions', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('success', async () => {
const actionSpy = jest.spyOn(Utils.prototype, 'action').mockResolvedValueOnce(false);
const actions = new Actions();
await actions.readFile();
expect(actionSpy).toHaveBeenCalledWith(5);
});
});
测试结果:
PASS examples/68879782/actions.test.ts (10.186 s)
actions
✓ success (3 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 71.43 | 100 | 75 | 71.43 |
actions.ts | 100 | 100 | 100 | 100 |
utils.ts | 33.33 | 100 | 50 | 33.33 | 5-6
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.827 s, estimated 11 s
正在使用打字稿测试调用实用程序 class 的 class。目标是模拟实用程序 class 并测试传递给调用的数据。
一个class待测试
import {Utils} from "~/src/play/utils";
export class Actions {
constructor() {
}
async readFile(): Promise<void> {
const utils = new Utils();
await utils.action(5)
}
}
const actions = new Actions();
actions.readFile()
实用程序class
export class Utils {
constructor() {}
async action(count: number): Promise<boolean> {
console.log(count);
return Promise.resolve(true);
}
}
测试脚本
// @ts-ignore
import {Utils} from "./utils";
import {Actions} from "~/src/play/actions";
const mockUtils = jest.fn();
jest.mock('../utils', () => {
return {
Utils: jest.fn().mockImplementation(() => {
return {
default: () => {return {utils: mockUtils}},
action: () => {
return 5;
}
}
})
}
})
describe('actions', () => {
beforeEach(() => {
// Utils.mockClear();
mockUtils.mockClear();
})
test('success', async () => {
const actions = new Actions()
await actions.readFile()
expect(mockUtils).toHaveBeenCalledWith(2)
})
})
它似乎没有接受模拟。结果是
Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: 2
Number of calls: 0
at Object.<anonymous> (/Users/jrobens/NetBeansProjects/azuron/winpay-uploader/src/play/__test__/actions.spec.ts:28:27)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
采纳@Stanislav Šolc 的建议添加 return 和参数值,包括 async
// @ts-ignore
import {Utils} from "../utils";
import {Actions} from "../actions";
const mockUtils = jest.fn();
jest.mock('../utils', () => {
return {
Utils: jest.fn().mockImplementation(() => {
return {
default: () => {return {utils: mockUtils}},
action: (count: number): Promise<boolean> => {
console.log(count);
return Promise.resolve(true);
}
}
})
}
})
结果不变
jest.mock() 中的模块路径必须与用于在测试单元中加载依赖项的路径完全相同。顺便说一句,这就是测试与测试单元位于同一目录中的原因(您可能不会这样做)。
并且您必须模拟模块的确切结构,当然还有方法的异步性质。因此,在您的情况下,您使用异步操作方法导出构造函数。所以这样的事情是更好的开始。
jest.mock('~/src/play/utils', () => {
return {
Utils: jest.fn().mockImplementation(() => {
return {action: jest.fn().mockResolvedValue(5)};
}
}
});
您可以使用 jest.spyOn(object, methodName) to mock Utils.prototype.action()
method. Use jest.restoreAllMocks() 将所有模拟恢复到 afterEach
挂钩中的原始值。防止mock的值影响其他测试用例。
例如
actions.ts
:
import { Utils } from './utils';
export class Actions {
constructor() {}
async readFile(): Promise<void> {
const utils = new Utils();
await utils.action(5);
}
}
utils.ts
:
export class Utils {
constructor() {}
async action(count: number): Promise<boolean> {
console.log(count);
return Promise.resolve(true);
}
}
actions.test.ts
:
import { Utils } from './utils';
import { Actions } from './actions';
describe('actions', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('success', async () => {
const actionSpy = jest.spyOn(Utils.prototype, 'action').mockResolvedValueOnce(false);
const actions = new Actions();
await actions.readFile();
expect(actionSpy).toHaveBeenCalledWith(5);
});
});
测试结果:
PASS examples/68879782/actions.test.ts (10.186 s)
actions
✓ success (3 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 71.43 | 100 | 75 | 71.43 |
actions.ts | 100 | 100 | 100 | 100 |
utils.ts | 33.33 | 100 | 50 | 33.33 | 5-6
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.827 s, estimated 11 s