Using Jest + TypeScript, how do I mock a static method used in another static method of a class being tested?

huangapple go评论86阅读模式
英文:

Using Jest + TypeScript, how do I mock a static method used in another static method of a class being tested?

问题

我有两个类 ClassAClassB,它们只包含静态方法。ClassA 中的一个方法叫做 staticMethodA(),它调用了 ClassB 中的一个静态方法,叫做 staticMethodB

  1. import { ClassB } from './classB';
  2. export class ClassA {
  3. public static async staticMethodA() {
  4. return await ClassB.staticMethodB();
  5. }
  6. }

在为 staticMethodA() 编写单元测试时,我希望模拟 staticMethodB() 以更好地隔离 staticMethodA()。根据现有的在线指南,我创建了以下测试:

  1. describe('staticMethodA', () => {
  2. let classA;
  3. const mockStaticMethodB = jest.fn().mockResolvedValue({}); // 返回一个虚拟对象
  4. beforeAll(() => {
  5. // 模拟 ClassB
  6. jest.mock('../src/classB', () => () => ({
  7. ClassB: {
  8. staticMethodB: mockStaticMethodB
  9. }
  10. })}};
  11. // 在模拟 ClassB 后导入 ClassA,以便它引用模拟
  12. classA = require('../src/classA');
  13. }
  14. it('应该调用 mockStaticMethodB', async () => {
  15. // 从 require 返回的对象是包含 ClassA 的对象
  16. const actual = await classA.ClassA.staticMethodA();
  17. expect(actual).toBe({}); // 虚拟对象
  18. }
  19. afterAll(() => {
  20. jest.unmock('../src/classB');
  21. });
  22. }

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.

  1. import { ClassB } from './classB'
  2. export class ClassA {
  3. public static async staticMethodA() {
  4. return await ClassB.staticMethodB();
  5. }
  6. }

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:

  1. describe('staticMethodA', () => {
  2. let classA;
  3. const mockStaticMethodB = jest.fn().mockResolvedValue({}); //return dummy object
  4. beforeAll(() => {
  5. // Mocking ClassB
  6. jest.mock('../src/classB', () => () => ({
  7. ClassB: {
  8. staticMethodB: mockStaticMethodB
  9. }
  10. })}};
  11. // Importing ClassA after mocking ClassB so it references the mock
  12. classA = require('../src/classA');
  13. }
  14. it('should call mockStaticMethodB', async () => {
  15. //The object returned from require is an object containing ClassA
  16. const actual = await classA.ClassA.staticMethodA();
  17. expect(actual).toBe({}); // dummyObject
  18. }
  19. afterAll(() => {
  20. jest.unmock('../src/classB');
  21. });
  22. }

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:

答案1

得分: 1

以下是代码的翻译部分:

  1. // classa.test.ts
  2. import { ClassA } from '../classA';
  3. // 直接导入了 ClassB
  4. // 这将是被模拟的版本
  5. import { ClassB } from '../classB';
  6. // 模拟应该提升到模块的顶部
  7. jest.mock('../classB', () => {
  8. return {
  9. ClassB: {
  10. staticMethodB: jest.fn(),
  11. },
  12. };
  13. });
  14. describe('classA', () => {
  15. it('应该调用 mockStaticMethodB', async () => {
  16. // 由于 ClassB 是一个模拟,我们可以为这个测试用例提供返回值
  17. (ClassB.staticMethodB as jest.Mock).mockReturnValueOnce(42);
  18. const actual = await ClassA.staticMethodA();
  19. // 请注意,在模拟和这里,我们都使用 42 进行比较,因为它适用于 `expect().toBe()`
  20. // 如果我们想要比较对象,我们将使用 `expect().toEqual()` 代替
  21. expect(actual).toBe(42);
  22. });
  23. });
英文:

There are a few things that would need changing in this case. I've tested this locally and it works.

  1. // classa.test.ts
  2. import {ClassA} from '../classA';
  3. // we are importing ClassB directly
  4. // this will be the mocked version
  5. import {ClassB} from '../classB';
  6. // mock should be hoisted to the top of the module
  7. jest.mock('../classB', () => {
  8. return {
  9. ClassB: {
  10. staticMethodB: jest.fn(),
  11. },
  12. };
  13. });
  14. describe('classA', () => {
  15. it('should call mockStaticMethodB', async () => {
  16. // since ClassB is a mock we can provide the return value for this test case only
  17. (ClassB.staticMethodB as jest.Mock).mockReturnValueOnce(42);
  18. const actual = await ClassA.staticMethodA();
  19. // note that in both mock and here we are using 42 for comparison as it works with `expect().toBe()`
  20. // if we wanted to compare objects we would use `expect().toEqual()` instead
  21. expect(actual).toBe(42);
  22. });
  23. });

huangapple
  • 本文由 发表于 2023年2月24日 03:24:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75549444.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定