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

问题描述 投票:0回答:1

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

    // 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 "

这是预期的吗?

我的测试有效吗?我在测试中错过了什么吗?

jestjs
1个回答
1
投票

发生的事情是,当 Jest 导入

fruit.js
以从中生成模拟时,默认导出中的匿名函数已经在其闭包中获取了对其实际
strawberry
的引用。

所以 Jest 所做的只是嘲笑

strawberry
稍后导入它的任何其他模块,例如你的测试套件。

本文介绍了解决此问题的一些方法:https://medium.com/@qjli/how-to-mock-specific-module-function-in-jest-715e39a391f4

我的建议是在采用任何解决方法之前考虑重构你的逻辑:

  • fruit.js
    中的某些函数是否用作实现细节或用于分解逻辑?也许您可以将它们视为私有类方法,并通过
    defaultExport
    本身来测试它们。

  • 如果它们的逻辑如此独立以至于需要在测试之间进行模拟,也许这些功能应该驻留在单独的模块中?

© www.soinside.com 2019 - 2024. All rights reserved.