使用玩笑创建模拟对象
Mock object creation using jest
我对玩笑测试还很陌生。我有以下实现 class
import { ExternalObject } from 'external-library';
export class MyClass {
public createInstance(settings : ISettings) : ExternalObject {
const setting1 = settings.getSetting("setting1");
const setting2 = settings.getSetting("setting2");
return new ExternalObject(setting1, setting2);
}
}
我正在尝试测试这个 class 并且我已经能够正确模拟设置。但是我无法模拟外部对象构造 new ExternalObject(setting1, setting2);
并且我的测试用例失败了,因为它正在尝试构造实际对象(由于传递的参数实际上不是有效值而失败)。
describe("Create Instance", () => {
test("Allow creation of external instance", () => {
// not sure if I am using this correctly?
// Aim is to mock out external module and any objects it may need creating
jest.mock('external-library', () => {
return {
ExternalObject: jest.fn().mockImplementation()
}
});
let settings: ISetting = new Settings();
jest.spyOn(settings, "getSetting")
.mockImplementationOnce(() => 'abcd')
.mockImplementationOnce(() => 'xyz')
let myImpl = new MyClass();
let inst = myImpl.createInstance(settings);
// expecting that the instance is created successfully.
expect(inst).toBeTruthy();
});
});
但是我不确定我在这里做错了什么。我确实浏览了文档和其他一些问题,但无法理解我遗漏了什么。
在函数范围内使用jest.mock()
,模拟模块不会被提升到代码块的顶部。这将导致 external-library
模块在导入被测试的代码时不会被模拟。只需将 jest.mock()
移动到测试文件的模块范围。
例如
MyClass.ts
:
//@ts-ignore
import { ExternalObject } from 'external-library';
import { ISettings } from './Settings';
export class MyClass {
public createInstance(settings: ISettings): ExternalObject {
const setting1 = settings.getSetting('setting1');
const setting2 = settings.getSetting('setting2');
return new ExternalObject(setting1, setting2);
}
}
Settings.ts
:
export interface ISettings {
getSetting(key: string): void;
}
export class Settings implements ISettings {
getSetting(key: string) {
return 'real implementation';
}
}
MyClass.test.ts
:
import { MyClass } from './MyClass';
import { ISettings, Settings } from './Settings';
//@ts-ignore
import { ExternalObject } from 'external-library';
jest.mock(
'external-library',
() => {
return { ExternalObject: jest.fn() };
},
{ virtual: true }
);
describe('68545423', () => {
afterEach(() => {
jest.restoreAllMocks();
});
afterAll(() => {
jest.resetAllMocks();
});
test('should pass', () => {
let myImpl = new MyClass();
let settings: ISettings = new Settings();
jest
.spyOn(settings, 'getSetting')
.mockImplementationOnce(() => 'abcd')
.mockImplementationOnce(() => 'xyz');
let inst = myImpl.createInstance(settings);
expect(inst).toBeTruthy();
expect(ExternalObject).toBeCalledWith('abcd', 'xyz');
});
});
测试结果:
PASS examples/68545423/MyClass.test.ts (7.233 s)
68545423
✓ should pass (4 ms)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 85.71 | 100 | 50 | 85.71 |
MyClass.ts | 100 | 100 | 100 | 100 |
Settings.ts | 50 | 100 | 0 | 50 | 7
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.032 s, estimated 9 s
Ran all test suites related to changed files.
我对玩笑测试还很陌生。我有以下实现 class
import { ExternalObject } from 'external-library';
export class MyClass {
public createInstance(settings : ISettings) : ExternalObject {
const setting1 = settings.getSetting("setting1");
const setting2 = settings.getSetting("setting2");
return new ExternalObject(setting1, setting2);
}
}
我正在尝试测试这个 class 并且我已经能够正确模拟设置。但是我无法模拟外部对象构造 new ExternalObject(setting1, setting2);
并且我的测试用例失败了,因为它正在尝试构造实际对象(由于传递的参数实际上不是有效值而失败)。
describe("Create Instance", () => {
test("Allow creation of external instance", () => {
// not sure if I am using this correctly?
// Aim is to mock out external module and any objects it may need creating
jest.mock('external-library', () => {
return {
ExternalObject: jest.fn().mockImplementation()
}
});
let settings: ISetting = new Settings();
jest.spyOn(settings, "getSetting")
.mockImplementationOnce(() => 'abcd')
.mockImplementationOnce(() => 'xyz')
let myImpl = new MyClass();
let inst = myImpl.createInstance(settings);
// expecting that the instance is created successfully.
expect(inst).toBeTruthy();
});
});
但是我不确定我在这里做错了什么。我确实浏览了文档和其他一些问题,但无法理解我遗漏了什么。
在函数范围内使用jest.mock()
,模拟模块不会被提升到代码块的顶部。这将导致 external-library
模块在导入被测试的代码时不会被模拟。只需将 jest.mock()
移动到测试文件的模块范围。
例如
MyClass.ts
:
//@ts-ignore
import { ExternalObject } from 'external-library';
import { ISettings } from './Settings';
export class MyClass {
public createInstance(settings: ISettings): ExternalObject {
const setting1 = settings.getSetting('setting1');
const setting2 = settings.getSetting('setting2');
return new ExternalObject(setting1, setting2);
}
}
Settings.ts
:
export interface ISettings {
getSetting(key: string): void;
}
export class Settings implements ISettings {
getSetting(key: string) {
return 'real implementation';
}
}
MyClass.test.ts
:
import { MyClass } from './MyClass';
import { ISettings, Settings } from './Settings';
//@ts-ignore
import { ExternalObject } from 'external-library';
jest.mock(
'external-library',
() => {
return { ExternalObject: jest.fn() };
},
{ virtual: true }
);
describe('68545423', () => {
afterEach(() => {
jest.restoreAllMocks();
});
afterAll(() => {
jest.resetAllMocks();
});
test('should pass', () => {
let myImpl = new MyClass();
let settings: ISettings = new Settings();
jest
.spyOn(settings, 'getSetting')
.mockImplementationOnce(() => 'abcd')
.mockImplementationOnce(() => 'xyz');
let inst = myImpl.createInstance(settings);
expect(inst).toBeTruthy();
expect(ExternalObject).toBeCalledWith('abcd', 'xyz');
});
});
测试结果:
PASS examples/68545423/MyClass.test.ts (7.233 s)
68545423
✓ should pass (4 ms)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 85.71 | 100 | 50 | 85.71 |
MyClass.ts | 100 | 100 | 100 | 100 |
Settings.ts | 50 | 100 | 0 | 50 | 7
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.032 s, estimated 9 s
Ran all test suites related to changed files.