使用Jest创建的部分模块模拟函数未被测试函数调用

raogr8fs  于 11个月前  发布在  Jest
关注(0)|答案(1)|浏览(126)

(基于已经提供的示例here。)对于下面的模块,

// fruit.js
    export const apple = 'apple';
    
    export const strawberry = () => 'strawberry';
    
    export default () => `banana and ${strawberry()} `;

字符串
我想写一个测试来验证 default * 导出的函数是否正确调用了函数 * strawberry。为了实现这一点,我尝试了以下测试:

// partial_mock.js
    import defaultExport, { strawberry } from '../fruit';
    
    jest.mock('../fruit', () => {
      const originalModule = require.requireActual('../fruit');
      const mockedModule = jest.genMockFromModule('../fruit');
    
      // Mock the exported 'strawberry' function.
      return Object.assign({}, mockedModule, originalModule, {
        strawberry: jest.fn(() => 'mocked strawberry'),
      });
    });
    
    it('does a partial mock', () => {
      expect(strawberry()).toBe('mocked strawberry');
    
      const defaultExportResult = defaultExport();
      expect(defaultExportResult).toBe('banana and mocked strawberry');
    });


然而,模拟的函数不会被调用,而是实际的函数被调用。

× does a partial mock (21ms)
    
      ● does a partial mock
    
        expect(received).toBe(expected) // Object.is equality
    
        Expected: "banana and mocked strawberry"
        Received: "banana and strawberry "


这是预期的吗?
我的测试有效吗?我的测试中有没有遗漏什么?

tzcvj98z

tzcvj98z1#

实际情况是,当Jest导入fruit.js并从中生成mock时,默认导出中的匿名函数已经在其闭包中获取了对实际strawberry的引用。
所以Jest所做的就是为以后导入它的任何其他模块模拟strawberry,例如您的测试套件。
本文介绍了解决此问题的一些方法:https://medium.com/@qjli/how-to-mock-specific-module-function-in-jest-715e39a391f4
我的建议是在使用任何变通方法之前考虑重构您的逻辑:

  • fruit.js中的某些函数是用作实现细节还是用于分解逻辑?也许您可以将它们视为私有类方法,并通过defaultExport本身测试它们。
  • 如果它们的逻辑是如此独立,以至于需要在测试之间进行模拟,那么这些功能是否应该驻留在单独的模块中?

相关问题