英文:
Using Jest + TypeScript, how do I mock a static method used in another static method of a class being tested?
问题
我有两个类 ClassA
和 ClassB
,它们只包含静态方法。ClassA
中的一个方法叫做 staticMethodA()
,它调用了 ClassB
中的一个静态方法,叫做 staticMethodB
。
import { ClassB } from './classB';
export class ClassA {
public static async staticMethodA() {
return await ClassB.staticMethodB();
}
}
在为 staticMethodA()
编写单元测试时,我希望模拟 staticMethodB()
以更好地隔离 staticMethodA()
。根据现有的在线指南,我创建了以下测试:
describe('staticMethodA', () => {
let classA;
const mockStaticMethodB = jest.fn().mockResolvedValue({}); // 返回一个虚拟对象
beforeAll(() => {
// 模拟 ClassB
jest.mock('../src/classB', () => () => ({
ClassB: {
staticMethodB: mockStaticMethodB
}
})}};
// 在模拟 ClassB 后导入 ClassA,以便它引用模拟
classA = require('../src/classA');
}
it('应该调用 mockStaticMethodB', async () => {
// 从 require 返回的对象是包含 ClassA 的对象
const actual = await classA.ClassA.staticMethodA();
expect(actual).toBe({}); // 虚拟对象
}
afterAll(() => {
jest.unmock('../src/classB');
});
}
当 staticMethodA
调用 staticMethodB
时,我收到一个错误,说 ClassB
未定义。当我在 return await ClassB.staticMethodB();
上设置断点时,我看到有一个名为 classB_1
的变量可用,但没有 ClassB
。
我尝试了一些在以下资源中找到的模拟构建策略,但仍然导致 ClassB
未定义:
英文:
I have two classes ClassA
and ClassB
that contain only static methods. One of the methods in ClassA
, called staticMethodA()
, calls a static method from ClassB
, called staticMethodB
.
import { ClassB } from './classB'
export class ClassA {
public static async staticMethodA() {
return await ClassB.staticMethodB();
}
}
While working on a unit test for staticMethodA()
, I wanted to mock staticMethodB()
to better isolate staticMethodA()
. Following existing guidance online, I created the following test:
describe('staticMethodA', () => {
let classA;
const mockStaticMethodB = jest.fn().mockResolvedValue({}); //return dummy object
beforeAll(() => {
// Mocking ClassB
jest.mock('../src/classB', () => () => ({
ClassB: {
staticMethodB: mockStaticMethodB
}
})}};
// Importing ClassA after mocking ClassB so it references the mock
classA = require('../src/classA');
}
it('should call mockStaticMethodB', async () => {
//The object returned from require is an object containing ClassA
const actual = await classA.ClassA.staticMethodA();
expect(actual).toBe({}); // dummyObject
}
afterAll(() => {
jest.unmock('../src/classB');
});
}
I get an error when staticMethodA calls staticMethodB that says that ClassB is undefined. When I set a breakpoint on return await ClassB.staticMethodB();
, I see there's a variable called classB_1
available but not ClassB
.
I've tried some of the mock construction strategies found in the following resources, but all still resulted in ClassB
being undefined:
- https://meticulous.ai/blog/mocking-a-javascript-class-with-jest-two-ways-to-make-it-easier/
- https://medium.com/@david-ting/jest-jest-typescript-mocking-static-method-42f420020a07
- https://www.linkedin.com/learning-login/share?account=88323306&forceAccount=false&redirect=https%3A%2F%2Fwww.linkedin.com%2Flearning%2Fnode-js-testing-and-code-quality-14003857%2Fmocking-module-dependencies%3Ftrk%3Dshare_video_url%26shareId%3DvzQuLJXkT%252Byp2r6dSqXYIQ%253D%253D
答案1
得分: 1
以下是代码的翻译部分:
// classa.test.ts
import { ClassA } from '../classA';
// 直接导入了 ClassB
// 这将是被模拟的版本
import { ClassB } from '../classB';
// 模拟应该提升到模块的顶部
jest.mock('../classB', () => {
return {
ClassB: {
staticMethodB: jest.fn(),
},
};
});
describe('classA', () => {
it('应该调用 mockStaticMethodB', async () => {
// 由于 ClassB 是一个模拟,我们可以为这个测试用例提供返回值
(ClassB.staticMethodB as jest.Mock).mockReturnValueOnce(42);
const actual = await ClassA.staticMethodA();
// 请注意,在模拟和这里,我们都使用 42 进行比较,因为它适用于 `expect().toBe()`
// 如果我们想要比较对象,我们将使用 `expect().toEqual()` 代替
expect(actual).toBe(42);
});
});
英文:
There are a few things that would need changing in this case. I've tested this locally and it works.
// classa.test.ts
import {ClassA} from '../classA';
// we are importing ClassB directly
// this will be the mocked version
import {ClassB} from '../classB';
// mock should be hoisted to the top of the module
jest.mock('../classB', () => {
return {
ClassB: {
staticMethodB: jest.fn(),
},
};
});
describe('classA', () => {
it('should call mockStaticMethodB', async () => {
// since ClassB is a mock we can provide the return value for this test case only
(ClassB.staticMethodB as jest.Mock).mockReturnValueOnce(42);
const actual = await ClassA.staticMethodA();
// note that in both mock and here we are using 42 for comparison as it works with `expect().toBe()`
// if we wanted to compare objects we would use `expect().toEqual()` instead
expect(actual).toBe(42);
});
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论