jest 里有两种 mock,一种是方法的 mock,还有一种是模块的 mock。这里我们来看一下模块的 mock 是如何实现的。

比如我们要 mock 掉 node 内置的 fs 模块,我们只要这么写:

const fs = require('fs');
jest.mock('fs');
console.log(fs.statSync('/tmp/file')); // undefined

jest 在执行这个文件的时候,首先会对代码进行转换,转换分成两步。

第一步是提升 jest.mock('fs') ,让它能作用在 require 之前,转换后的代码如下:

jest.mock('fs');
const fs = require('fs');
jest.mock('fs');
console.log(fs.statSync('/tmp/file'));

第二部是包一层匿名方法,这一步跟 node 的模块实现类似:

(function(module, exports, require, __dirname, __filename, global, jest){
  jest.mock('fs');
  const fs = require('fs');
  console.log(fs.statSync('/tmp/file'));
 

代码转换完后,jest 需要注入自己的 require 实现,这个一步通过让转换后的代码在 vm 模块创建的新的上下文里执行,最终生成一个可以执行的匿名方法实现。

const vm = require('vm');
const code = '转换后的代码';
const script = new vm.Script(code);
const result = script.runInContext(context); // describe, it 等全局方法在这里注入
result.call(
  module,
  exports,
  require, // jest 自己的 require 实现,
 

最后,我们用伪代码来描述下 require 的实现:

const shouldMock = {};
function mock(moduleName) {
  // jest 会给每个模块生成一个 moduleId, 比如这里是 `node:fs:` 表示这是一个 node 模块
  const moduleId = getModuleId(moduleName);
  shouldMock[moduleId] = true;
// 这个就是 jest 给我们的代码注入的 require 方法
function requireModuleOrMock(moduleName) {
  if(shouldMock(moduleName)) {
    return requireMockModule(moduleName);
  } else {
    return requireModule(moduleName);
function shouldMock(moduleName) {
  const moduleId = getModuleId(moduleName);
  return moduleId in shouldMock;
function requireMockModule(moduleName) {
  const moduleExports =  requireModule(moduleName);
  return Object.keys(moduleExports).reduce((mock, key) => {
    mock[key] = () => {}; // mock 的方法
    return mock;
  }, {})
function requireModule(moduleName) {
  return require(moduleName); // 这个是原始的 require
                    jest 里有两种 mock,一种是方法的 mock,还有一种是模块的 mock。这里我们来看一下模块的 mock 是如何实现的。比如我们要 mock 掉 node 内置的 fs 模块,我们只要这么写:const fs = require('fs');jest.mock('fs');console.log(fs.statSyn...
 import * as mock from "jest-mock-module" ;
mock . extend ( jest ) ;
jest . spy ( "src/example" ) ;
const example = require ( "src/example" ) ;
// Check module object properties
下面介绍mock 的一些方法使用:
首先需要了解:jest.fn()
jest.fn()是创建Mock函数最简单的方式,如果没有定义函数内部的实现,jest.fn()会返回undefined作为返回值。
test('测试jest.fn()调用', () => {
  let mockFn = jest.fn();
  let resu
为什么会用到 MockMock 能帮我们解决什么问题?
在项目中,一个模块的方法内常常会去调用另外一个模块的方法。在单元测试中,我们可能并不需要关心内部调用的方法的执行过程和结果,只想知道它是否被正确调用即可,甚至会指定该函数的返回值。此时,使用Mock函数是十分有必要。
Mock函数提供的以下三种特性,在我们写测试代码时十分有用:
- 擦除函数的实际实现(换句话说:改变函数的内部实现)
- 捕获函数调用情况( 包括:这些调用中
				
转载React16 Jest单元测试 之 Mock Functions(Mocking Modules 和 Mock Implementations)项目初始化【这里使用之前的项目,节省时间】项目初始化地址https://github.com/durban89/webpack4-react16-reactrouter-demo.git tag:v_1.0.21拉取git clone https:/...
Jest是由Facebook开发并维护的一套js的单元测试框架,之前在后台的nodejs项目里面第一次尝试使用,感觉还是非常容易上手的,功能也比较强大。尤其是mock方面也别好用,还天然的支持覆盖率,所以非常推荐使用。 内置支持的功能如下: 灵活的配置:比如,可以用文件名通配符来检测测试文件; 测试的事前步骤(Setup)和事后步骤(Teardown),同时也包括测试范围; 匹配表达...
单元测试某些场景下只想模拟模块中的某个功能,并且保留模块原有的功能。这时候我可以用 jest.requireActual 配合 jest.mock 进行实现。 jest.requireActual 该API返回实际模块而不是模拟模块,绕过所有有关该模块是否应接收模拟实施的检查。为什么用 jest.requireActual ? 因为jestmock中是不允许直接使用全局变量,所以我们无法直接import模块包装实现。 模拟Taro的login API jest.mock('@tarojs/tar.
1. 使用 jest.spyOn() 函数替代 useEffect 的回调函数。 2. 使用 jest.runOnlyPendingTimers() 函数模拟 React 组件的生命周期。 3. 使用 act() 函数包裹你的测试代码,以确保测试的可预测性。 代码示例: import React, { useEffect } from 'react'; import { act, render, unmountComponentAtNode } from '@testing-library/react'; import { useFetch } from './useFetch'; jest.mock('./useFetch', () => { return { useFetch: jest.fn().mockImplementation(() => ({ data: null, loading: true, error: null, describe('useFetch', () => { let container: any; beforeEach(() => { container = document.createElement('div'); document.body.appendChild(container); afterEach(() => { unmountComponentAtNode(container); container.remove(); it('should call useFetch hook', () => { const spy = jest.spyOn(React, 'useEffect'); const { useFetch } = require('./useFetch'); act(() => { render(<App />, container); expect(spy).toHaveBeenCalled(); spy.mockRestore();