JavaScript 测试 - 使用 jest 模拟来自同一模块的函数

标签 javascript unit-testing webpack jestjs

一段时间以来,我一直试图寻找这个问题的答案,但我失败了。所以我决定在这里尝试一下。如果已经有这样的问题而我错过了,我很抱歉重复。

假设我有这个 javascript 模块“myValidator.js”,其中有两个函数,一个函数调用另一个函数。

export const validate = (value) => {
  if (!value.something) {
    return false
  }

  // other tests like that
  return true
}

export const processValue = (value) => {
  if (!validate(value)) {
    return null
  }

  // do some stuff with value and return something
}

像这样测试这个。 我想测试验证功能,是否行为正确。然后我有 processValue 函数,它调用第一个函数并在验证正常或为 null 时返回一些值。

import * as myValidator from './myValidator'

describe('myValidator', () => {
  describe('validate', () => {
    it('should return false when something not defined', () => {
      ...
    }
  }

  describe('processValue', () => {
    it('should return something when value is valid', () => {
      const validateMock = jest.spyOn(myValidator, 'validate')
      validateMock.mockImplementation(() => true)
      expect(validate('something')).toEqual('somethingProcessed')
    }

    it('should return null when validation fails', () => {
      const validateMock = jest.spyOn(myValidator, 'validate')
      validateMock.mockImplementation(() => false)
      expect(validate('somethingElse')).toEqual(null)
    }
  }
}

现在,问题是这实际上不起作用,因为 processValue() 实际上调用模块内部的函数,因为我想是闭包的缘故。所以这个函数没有被模拟,因为我猜只有导出中的引用被更改为 Jest 模拟。

我已经找到了一个解决方案,并在模块内部使用

if (!exports.validate(value)) 

这适用于测试。然而,我们使用 Webpack (v4) 构建应用程序,因此它将这些导出转换为自己的结构,然后当应用程序启动时,exports 未定义,代码失败。

测试这个的最佳解决方案是什么?

当然,我可以通过提供一些有效和无效的值来做到这一点,对于这个可行的简单案例,但我认为它应该单独测试。

或者最好不要模拟函数并通过调用它来避免我遇到的问题,或者有什么方法可以用 JavaScript 模块实现这个?

最佳答案

我终于找到了这个问题的答案。它实际上在 Jest examples project on GitHub 中.

// Copyright 2004-present Facebook. All Rights Reserved.

/**
 * This file illustrates how to do a partial mock where a subset
 * of a module's exports have been mocked and the rest
 * keep their actual implementation.
 */
import defaultExport, {apple, strawberry} from '../fruit';

jest.mock('../fruit', () => {
  const originalModule = jest.requireActual('../fruit');
  const mockedModule = jest.genMockFromModule('../fruit');

  //Mock the default export and named export 'apple'.
  return {
    ...mockedModule,
    ...originalModule,
    apple: 'mocked apple',
    default: jest.fn(() => 'mocked fruit'),
  };
});

it('does a partial mock', () => {
  const defaultExportResult = defaultExport();
  expect(defaultExportResult).toBe('mocked fruit');
  expect(defaultExport).toHaveBeenCalled();

  expect(apple).toBe('mocked apple');
  expect(strawberry()).toBe('strawberry');
});

关于JavaScript 测试 - 使用 jest 模拟来自同一模块的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52610691/

相关文章:

javascript - 刷新页面后 jQuery 日期选择器不起作用

javascript - 如何将模块添加到我的 SystemJs 配置文件中,以便我可以以 Angular 导入它

unit-testing - 当测试特定条件/场景时,是否需要检查之前和之后的结果?

webpack - PDFmake:pdfmake.createPdf 不是函数

reactjs - 如何使用 create-react-app 创建包含 Web3 的 React App?我收到模块未找到错误。重大变化 : webpack < 5 used

javascript - 来自 Mithril promise 链内的 ReferenceError 被默默地忽略

asp.net - 使用 Javascript 的 ASP.NET ID 的正则表达式

c# - 测试自定义 AuthorizationAttribute 时抛出 NullReferenceException

angularjs - 如何对调用父组件方法的组件中的函数进行单元测试

javascript - 获取未找到原始 fs 模块的警告