【问题标题】:How to mock an encapsulated dependency with Jest?如何用 Jest 模拟封装的依赖项?
【发布时间】:2021-12-01 20:50:12
【问题描述】:

我正在尝试模拟在我正在测试的类内部实例化的类的方法的返回值,而不是在其余测试中保留模拟值。

这是我整理的一个非常基本的演示:

Mystery.ts

export class Mystery {
    private max = 10;

    public getNumber(): number {
        return Math.random() * this.max;
    }
}

TestedClass.ts

import { Mystery } from './Mystery';

export class TestedClass {
    public someMethod() {
        const numberGenerator = new Mystery();

        return numberGenerator.getNumber();
    }
}

TestedClass.test.ts

import { Mystery } from './Mystery';
import { TestedClass } from './TestedClass';

jest.mock('./Mystery');

describe('TestedClass', () => {
    beforeEach(jest.clearAllMocks);

    it('should return the number 1000', () => {
        // I want to have Mystery.getNumber() return 1000 for this test only.

        Mystery.prototype.getNumber = jest.fn().mockReturnValue(1000);
        // jest.spyOn(Mystery.prototype, 'getNumber').mockReturnValue(1000);
        // Mystery.prototype.getNumber = jest.fn().mockReturnValueOnce(1000);

        const provider = new TestedClass();
        const result = provider.someMethod();

        expect(result).toEqual(1000);
    });

    it('should return undefined', () => {
        const provider = new TestedClass();
        const result = provider.someMethod();

        // Expects: undefined, Received: 1000
        expect(result).toEqual(undefined);
    });
});

正如您从测试中看到的,我看到1000 出现在我想避免的第二个测试中。在真实场景中,所有测试都可能需要模拟 Mystery.getNumber() 的返回值(以不同的方式),但我想确保一个测试不会像现在这样影响另一个测试。

这种当前行为确实有意义,因为我正在更改 Mystery.prototype,但我不确定如何以任何其他方式模拟单个测试的值。我也知道使用组合,这在这里会有很大帮助,但为了这个问题,我想避免这种情况。

【问题讨论】:

  • 你读过jestjs.io/docs/es6-class-mocks吗?这包括嘲笑班级。还有依赖倒置,传入Mystery 的实例,而不是将TestedClass 传递给新的实例;这将大大减少耦合并使测试变得微不足道。

标签: javascript typescript unit-testing testing jestjs


【解决方案1】:

如果您尝试仅为单个测试用例而不是所有测试用例模拟 getNumber 方法,则 jest.fn().mockReturnValueOnce 方法应该可以解决问题。

所以不是

Mystery.prototype.getNumber = jest.fn().mockReturnValue(1000);

使用

Mystery.prototype.getNumber = jest.fn().mockReturnValueOnce(1000);

【讨论】:

  • 所有测试用例都需要以不同的方式模拟返回值。我只是不希望一项测试影响另一项测试。我已经更新了这个问题,希望能澄清
  • @RyanPeterson 感谢您的澄清。我已经更新了答案以增加清晰度。希望对你有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 2020-10-17
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
相关资源
最近更新 更多