如何在 Jest 的 beforeEach 中监视实例化的 class?
How to spy a class instantiated within beforeEach in Jest?
我有一个 class 实例应该在每次测试之间清除,所以我这样做:
class Foo {
constructor() {}
public bar() {
return console.log("bar")
}
}
describe('tests on class Foo', () => {
let foo: Foo
beforeEach(() => {
foo = new Foo()
jest.clearAllMocks()
})
const spyOnBar = jest.spyOn(foo, "bar")
test("should call bar", () => {
foo.bar()
expect(spyOnBar).toHaveBeenCalled()
})
})
但是 spyOnBar
一直给我错误 Cannot spyOn on a primitive value; undefined given
。
有没有一种方法可以监视方法栏而无需在每个测试中声明间谍?
参见 Order of execution of describe and test blocks。
让我们看看执行的顺序。
describe('tests on class Foo', () => {
beforeEach(() => {
console.log('beforeEach');
});
console.log('describe');
test('should call bar', () => {
console.log('test');
});
});
日志:
PASS Whosebug/72035574/foo.test.ts (10.376 s)
tests on class Foo
✓ should call bar (2 ms)
console.log
describe
at Suite.<anonymous> (Whosebug/72035574/foo.test.ts:16:11)
console.log
beforeEach
at Object.<anonymous> (Whosebug/72035574/foo.test.ts:13:13)
console.log
test
at Object.<anonymous> (Whosebug/72035574/foo.test.ts:20:13)
当您在 describe
块中调用 jest.spyOn(foo, 'bar')
方法时,尚未创建 foo
实例。这就是您收到错误的原因。
选项 1. 在 describe
块中创建 foo
实例并在其方法上添加监视。由于所有测试用例共享一个 foo
实例和间谍,我们需要在 beforeEach
钩子中调用 jest.clearAllMocks()
来清除 mock.calls
和 mock.instances
属性,以便每个测试案件将使用明确的间谍对象。 toBeCalledTimes(1)
会起作用。
class Foo {
constructor() {}
public bar() {
return console.log('bar');
}
}
describe('tests on class Foo', () => {
const foo = new Foo();
const spyOnBar = jest.spyOn(foo, 'bar');
beforeEach(() => {
jest.clearAllMocks();
});
test('should call bar', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
test('should call bar - 2', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
});
选项 2. 创建 foo
并监视 beforeEach
挂钩,以便每个测试用例都使用一个新的。没有必要使用 jest.clearAllMocks()
.
describe('tests on class Foo', () => {
let spyOnBar: jest.SpyInstance;
let foo: InstanceType<typeof Foo>;
beforeEach(() => {
foo = new Foo();
spyOnBar = jest.spyOn(foo, 'bar');
});
test('should call bar', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
test('should call bar - 2', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
});
我有一个 class 实例应该在每次测试之间清除,所以我这样做:
class Foo {
constructor() {}
public bar() {
return console.log("bar")
}
}
describe('tests on class Foo', () => {
let foo: Foo
beforeEach(() => {
foo = new Foo()
jest.clearAllMocks()
})
const spyOnBar = jest.spyOn(foo, "bar")
test("should call bar", () => {
foo.bar()
expect(spyOnBar).toHaveBeenCalled()
})
})
但是 spyOnBar
一直给我错误 Cannot spyOn on a primitive value; undefined given
。
有没有一种方法可以监视方法栏而无需在每个测试中声明间谍?
参见 Order of execution of describe and test blocks。
让我们看看执行的顺序。
describe('tests on class Foo', () => {
beforeEach(() => {
console.log('beforeEach');
});
console.log('describe');
test('should call bar', () => {
console.log('test');
});
});
日志:
PASS Whosebug/72035574/foo.test.ts (10.376 s)
tests on class Foo
✓ should call bar (2 ms)
console.log
describe
at Suite.<anonymous> (Whosebug/72035574/foo.test.ts:16:11)
console.log
beforeEach
at Object.<anonymous> (Whosebug/72035574/foo.test.ts:13:13)
console.log
test
at Object.<anonymous> (Whosebug/72035574/foo.test.ts:20:13)
当您在 describe
块中调用 jest.spyOn(foo, 'bar')
方法时,尚未创建 foo
实例。这就是您收到错误的原因。
选项 1. 在 describe
块中创建 foo
实例并在其方法上添加监视。由于所有测试用例共享一个 foo
实例和间谍,我们需要在 beforeEach
钩子中调用 jest.clearAllMocks()
来清除 mock.calls
和 mock.instances
属性,以便每个测试案件将使用明确的间谍对象。 toBeCalledTimes(1)
会起作用。
class Foo {
constructor() {}
public bar() {
return console.log('bar');
}
}
describe('tests on class Foo', () => {
const foo = new Foo();
const spyOnBar = jest.spyOn(foo, 'bar');
beforeEach(() => {
jest.clearAllMocks();
});
test('should call bar', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
test('should call bar - 2', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
});
选项 2. 创建 foo
并监视 beforeEach
挂钩,以便每个测试用例都使用一个新的。没有必要使用 jest.clearAllMocks()
.
describe('tests on class Foo', () => {
let spyOnBar: jest.SpyInstance;
let foo: InstanceType<typeof Foo>;
beforeEach(() => {
foo = new Foo();
spyOnBar = jest.spyOn(foo, 'bar');
});
test('should call bar', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
test('should call bar - 2', () => {
foo.bar();
expect(spyOnBar).toBeCalledTimes(1);
});
});