首页
Preview

Jest — 如何在模块内模拟函数调用

JEST标志

假设你有以下文件:

// f.jsexport function b(){
  return 'b';
}export function a(){
  return b();
}

如果你想要mock b来测试a,好的……它并不像看起来那么简单。

初学者的方法

我最初尝试的是:

test('a', () => {
  const f = require('./f');  jest.spyOn(f, 'b').mockReturnValue('c');  expect(f.a()).toBe('c');
  // FAILED!
  // expected 'c' got 'b'
})

不行……不会起作用。

这是因为导出的b确实被mock了,但它不是模块内被a调用的那个b

解决方案1——将模块拆分为不同的文件

如果你将b移到它自己的文件中:

// b.jsexport function b(){
  return 'b';
}// f.jsimport {b} from './b';export function a(){
  return b();
}

那么测试将通过:

test('a', () => {
  const b = require('./b');
  const f = require('./f');  jest.spyOn(b, 'b').mockReturnValue('c');  expect(f.a()).toBe('c');
  //PASSED!
})

这看起来是最干净的解决方案,但如果你想把你的函数保留在同一个文件中怎么办呢?

解决方案2——使用导出调用mocked函数

在调用函数之前添加exports.

// f.jsexport function b(){
  return 'b';
}export function a(){
  return exports.b();
}

然后测试将通过:

test('a', () => {
  const f = require('./f');  jest.spyOn(f, 'b').mockReturnValue('c');  expect(f.a()).toBe('c');
  //PASSED!
})

我真的很喜欢这个解决方案,因为你只需要在测试的文件中更改一些微不足道的东西。此外,即使可以避免这个小变化:

你可以使用这个库 babel-plugin-explicit-exports-references 来自动将同一模块中的所有函数添加 exports.

请注意,该库非常新,受众非常小。在安全方面要谨慎使用。

值得一提的次优解——导出命名空间对象

你可以创建一个命名空间,将其作为默认对象导出,并使用命名空间调用b

这样,当你调用jest.mock时,它将替换命名空间对象上的b函数。

// f.jsconst f = {
  b(){
    return 'b';
  },  a(){
    return f.b();
  }
};export default f;

然后测试将通过:

test('a', () => {
  const f = require('./f');  jest.spyOn(f, 'b').mockReturnValue('c');  expect(f.a()).toBe('c');
  //PASSED!
})

但是你需要将其作为默认导入导入,而不能将其分解为命名导出。

// won't work:
// import {a} from './f';import f from './f';...f.a();

有点丑陋。

另一种次优解——使用重写库

babel-plugin-rewire是一个会改变模块内部内容的侵入性库。

它似乎不是一个非常受欢迎的库,而且它实际上对我没有起作用,因为它不支持TypeScript,但这里大致介绍一下它的工作原理——

你不需要改变你正在测试的文件中的任何内容。

// f.jsexport function b(){
  return 'b';
}export function a(){
  return b();
}

在测试中重写b函数:

import {a, __set__} from './f';test('a', () => {
  const f = require('./f');  // This rewires b to return 'c'
  __set__('b', () => 'c');  expect(f.a()).toBe('c');
  // PASSED!})

愉快的测试 :)

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
一个人玩
先找到想要的,然后出发

评论(0)

添加评论