为啥 jest v24 模拟类需要私有方法

Posted

技术标签:

【中文标题】为啥 jest v24 模拟类需要私有方法【英文标题】:why is jest v24 mocking class requiring private methods为什么 jest v24 模拟类需要私有方法 【发布时间】:2019-07-07 21:12:18 【问题描述】:

我需要使用 jest v24+ 创建我的打字稿类的模拟实现。我特别想创建一个模拟类,该类被注入到构造函数中并模拟将被调用以返回特定响应的函数。

如何为每个测试创建一个模拟?

更多信息:

我已经开始了一个新项目,现在正在使用 jest v24,它在编写测试时产生了一个我无法解决的问题。

在 jest v23 中使用下面的示例,以前我可以模拟 Randomiser 类,如下所示:

const Mock = jest.fn<Randomiser>(() => (
  getRandom: jest.fn().mockReturnValue(10)
));

这将成功编译和构建。

从 v24 开始,fn 函数采用并添加通用 &lt;T, Y extends any[]&gt; 我不知道这是否与行为改变有关,但现在我收到一个错误:

类型 ' getRandom: Mock; 中缺少属性 'rand' ' 但在 'Randomiser'.ts(2741) 类型中是必需的

import "jest";

class Randomiser 
    public getRandom(): number 
        return this.rand();
    
    private rand(): number 
        return Math.random();
    


class Multiplier 
    private randomiser: Randomiser;
    constructor(randomiser: Randomiser) 
        this.randomiser = randomiser;
    

    multiplyRandom(factor: number): number 
        return Math.floor(this.randomiser.getRandom() * factor);
    


describe("tests", () => 
    it("10 x 2 = 20", () => 
        const Mock = jest.fn<Randomiser, any>(() => (
            getRandom: jest.fn().mockReturnValue(10),
            rand: jest.fn() //with this line I get an error because it should be private, without this line I get the error above.
        ));
        expect(new Multiplier(new Mock()).multiplyRandom(2)).toBe(20);
    )
)

我希望能够像使用 v23 一样编写我的模拟,即我可以模拟类并且只需要模拟我要调用的函数。

现在我必须模拟所有函数,包括它抱怨的私有函数和私有属性不是私有的。

【问题讨论】:

【参考方案1】:

两种解决方案:

1.使用Partial&lt;Type&gt;,这将允许您部分模拟您的课程:

const Mock = jest.fn<Partial<Randomiser>, []>(() => (
  getRandom: jest.fn().mockReturnValue(10)
));

然后将你的模拟转换为你的类类型以注入它,例如:

const mock: Randomiser = new Mock() as Randomiser;
expect(new Multiplier(mock).multiplyRandom(2)).toBe(20);

2。不要为模拟指定任何类型。

另一种方法是不指定模拟的类型,这使得模拟类型为any

const Mock = jest.fn(() => (
  getRandom: jest.fn().mockReturnValue(10)
));

然后你可以直接注入你的mock,当然,在这种情况下它不会被输入。

const mock = new Mock();
expect(new Multiplier(mock).multiplyRandom(2)).toBe(20);

【讨论】:

谢谢,自从 jest 24 以来,我无法部分模拟课程,我不知道部分课程,谢谢!

以上是关于为啥 jest v24 模拟类需要私有方法的主要内容,如果未能解决你的问题,请参考以下文章

模拟安装挂钩 Jest 测试单元

Jest React 测试 es6 导入/导出不需要的模拟

如何使用 jest.fn() 模拟属性

Jest - 在另一个模块函数中模拟函数

如何使用 Jest 模拟 JavaScript 窗口对象?

如何在带有 Jest 的 react-native 中使用模拟的 fetch() 对 API 调用进行单元测试