如何使用 jest 模拟私有变量

Posted

技术标签:

【中文标题】如何使用 jest 模拟私有变量【英文标题】:How to use jest to mock out a private variable 【发布时间】:2020-02-23 06:11:29 【问题描述】:

我正在尝试为这样的函数编写单元测试:

export class newClass 
    private service: ServiceToMock;

    constructor () 
    this.service = new ServiceToMock()
    

    callToTest () 
        this.service.externalCall().then(()=> 
        //Code to test
        )
    

为了测试这段代码,我需要模拟服务,因为它调用了类之外的函数,但问题是它是私有的。

我究竟如何用 jest 模拟私有变量?该类创建了自己的实例,因此甚至可以模拟出来吗?

【问题讨论】:

为什么不能使用if (process.env.NODE_ENV === 'test') this.service = new MockedService(); else this.service = new ServiceToMock(); 我不知道你能做到这一点。不过,仅仅为了测试而更改生产代码似乎并不理想。 你能编辑你的代码吗?您的代码不正确 How to write unit testing for Angular / TypeScript for private methods with Jasmine的可能重复 但标题是 Jest,不是 Jasmine 【参考方案1】:

在您的实施中,您可以导入服务

implementation.js
import ServiceToMock from './serviceToMock.js';
implementation.spec.js
// import the already mocked service
import ServiceToMock from './serviceToMock.js';
import newClass from './implementation';

// auto-mock the service
jest.mock('./serviceToMock.js');

describe('newClass', () => 
  describe('somMethod', () => 
    beforeAll(() => 
      // it is recommended to make sure
      // the previous calls are cleared
      // before writing assertions
      ServiceToMock.prototype.externalCall.mockClear()

      // jest's auto-mocking will create jest.fn()
      // for each of the service's methods
      // and you will be able to use methods like .mockResolvedValue
      // to modify the mock behavior
      ServiceToMock.prototype.externalCall.mockResolvedValue(data);

      // call your method
      (new newClass).someMethod();
    );

    it('should call ServiceToMock.externalCall', () => 
      // and you can write assertions for the mocked methods
      expect(ServiceToMock.prototype.externalCall).toHaveBeenCalledWith();
    );
  );
);

working example without Types

或者在文件中有实现

在这种情况下,您必须测试这两个类,因为那是您的单元

【讨论】:

我的 externalCall 方法返回 void 所以 mockClear() 和 mockResolvedValue 不起作用。 @MatTaNg 如果它返回 void 你不应该能够链接 .then 并且你需要模拟清除,因为它在内部存储调用 它实际上返回了一个承诺。我在看错误的功能。尽管如此,它还是不知道那些模拟函数是什么 @MatTaNg 我已经用一个工作示例更新了我的答案 github.com/facebook/jest/issues/2227 - 展示了一种更简洁的方式

以上是关于如何使用 jest 模拟私有变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JEST 测试中模拟全局 Vue.js 变量

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

如何使用 gmock 模拟修改 C++ 类中的私有变量的成员函数?

如何使用 jest.fn() 在 jest 中使用 typescript 模拟函数

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

如何使用 Jest 模拟异步函数