javascript - 在逐个测试的基础上开 Jest 模拟类方法

标签 javascript unit-testing mocking jestjs

我正在尝试使用返回 JSON 的方法模拟实用程序库类。

实际库结构

module.exports = class Common() {
  getConfig() {
  return {
    real: 'data'
  }
}

被测文件如下:


const Common = require('./common');
const common = new Common();
const config = common.getConfig();

...

const someFunction = function() {
  // config.real is used inside this function
}

我正在尝试模拟 Common 类并为每个 Jest 测试返回不同的配置 JSON。

const fileUnderTest = require('./../fileUnderTest.js');
const Common = require('./../common.js');
jest.mock('./../common.js');

describe('something', () => {
  it('test one', () => {
    Common.getConfig = jest.fn().mockImplementation(() => {
      return {
        real : 'fake' // This should be returned for test one
      };
    });

    fileUnderTest.someFunction(); //config.real is undefined at this point
  });

  it('test two', () => {
  Common.getConfig = jest.fn().mockImplementation(() => {
      return {
        real : 'fake2' // This should be returned for test two
      };
    });
  })
})

是否可以在测试文件顶部设置 common.js 的 automock 创建的 mock 类方法的返回值?

我已经尝试使用 mockReturnValueOnce() 等。

最佳答案

jest.mock

在这种情况下,你真的不需要自动模拟整个 common 模块,因为你只是替换一个方法的实现,所以 jest.mock('./../common'); 不是必需的。

Common.getConfig

getConfig 是一个 prototype method所以 getConfig 存在于 Commonprototype 上。要模拟它,请使用 Common.prototype.getConfig 而不是 Common.getConfig

在 fileUnderTest.js 中配置

Common 的一个实例被创建并且 config 被设置为调用 common.getConfig() 的结果fileUnderTest 运行,这在需要时立即发生,因此 Common.prototype.getConfig 的 mock 必须到位你调用require('./../fileUnderTest')之前。


const Common = require('./../common');
Common.prototype.getConfig = jest.fn().mockImplementation(() => ({ real: 'fake' }));
const fileUnderTest = require('./../fileUnderTest');

describe('something', () => {
  it('should test something', () => {
    fileUnderTest.someFunction();  // config.real is 'fake' at this point
  });
});

更新

要对config.real 进行不同的每次测试 模拟这样的代码需要modules be reset测试之间:

describe('something', () => {
  afterEach(() => {
    jest.resetModules();  // reset modules after each test
  })

  it('test one', () => {
    const Common = require('./../common');
    Common.prototype.getConfig = jest.fn().mockImplementation(() => ({ real: 'fake' }));
    const fileUnderTest = require('./../fileUnderTest');
    fileUnderTest.someFunction();  // config.real is 'fake'
  });

  it('test two', () => {
    const Common = require('./../common');    
    Common.prototype.getConfig = jest.fn().mockImplementation(() => ({ real: 'fake2' }));
    const fileUnderTest = require('./../fileUnderTest');
    fileUnderTest.someFunction();  // config.real is 'fake2'
  })
})

重置模块是必要的,因为一旦需要一个模块,它就会被添加到模块缓存中,并且每次需要时都会返回同一个模块,除非模块被重置。

关于javascript - 在逐个测试的基础上开 Jest 模拟类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55190252/

相关文章:

javascript - ember - 关闭操作会导致错误,除非在组件中提供操作,否则不会呈现页面

Php 引荐来源网址是否有效?

javascript - jquery 在悬停时显示当前元素

unit-testing - 您如何调整单元测试以应对不断变化的需求?

c# - 模拟对象上的异步回调不等待

java - Mockito 模拟不适用于此方法。难道我做错了什么?

javascript - OPL 脚本中的幂函数

c# - 在大型依赖对象图上注入(inject)模拟

iphone - 如何使用核心数据进行单元测试?

python - 模块级别的模拟字典