React 16 Jest使用ES模块导入和模拟JSDOM中未实现的方法

转载

React 16 Jest使用ES模块导入和模拟JSDOM中未实现的方法

项目初始化

git clone https://github.com/durban89/webpack4-react16-reactrouter-demo.git 
cd webpack4-react16-reactrouter-demo
git fetch origin
git checkout v_1.0.28
npm install

Using with ES module imports(使用ES模块导入)

我们在使用ES模块时做导入的时候,会习惯性的将导入的语句放在测试文件的顶部。但是在使用Jest的时候,需要指示Jest在模块使用之前进行模拟操作。
正是由于这个原因,Jest会自动将jest.mock的调用提升到模块的顶部(在任何导入之前)

Mocking methods which are not implemented in JSDOM(模拟JSDOM中未实现的方法)

如果某些代码在使用JSDOM(Jest使用的DOM实现)尚未实现的方法的时候,这个情况在测试时是比较麻烦的。比如我们调用window.matchMedia()的时候,Jest返回TypeError:window.matchMedia不是函数,并且没有正确执行测试。
在这种情况下,在测试文件中模拟matchMedia就可以解决类似的问题:如下

window.matchMedia = jest.fn().mockImplementation(query => {
  return {
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(),
    removeListener: jest.fn(),
  };
});

如果window.matchMedia()用于在测试中调用的函数(或方法),则此方法有效。
如果window.matchMedia()直接在测试文件中执行,则Jest报告相同的错误。
在这种情况下,解决方案是将手动模拟移动到单独的文件中,并在测试文件之前将其包含在测试中:实例如下

import './matchMedia.mock'; // Must be imported before the tested file
import { myMethod } from './file-to-test';

describe('myMethod()', () => {
  // Test the method here...
});


这里官方就是简单的介绍了下,导致有些学者可能还是云里雾里的,下面简单的写个实例
创建文件
src/lib/matchMedia.mock.js

window.matchMedia = jest.fn().mockImplementation((query) => {
  const obj = {
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(),
    removeListener: jest.fn(),
  };

  return obj;
});

src/lib/useMatchMedia.js

const useMatchMedia = () => {
  const res = window.matchMedia;
  return res;
};

module.exports = {
  useMatchMedia,
};


创建完文件后,添加测试文件
src/__tests__/useMatchMedia.test.js
第一次我们不调用src/lib/matchMedia.mock.js这个文件

// import '../lib/matchMedia.mock';
import { useMatchMedia } from '../lib/useMatchMedia';

describe('useMatchMedia()', () => {
  it('useMatchMedia() 被调用', () => {
    const res = useMatchMedia();
    expect(res).toBeUndefined();
    // expect(res).toBeDefined();
  });
});


第二次我们调用src/lib/matchMedia.mock.js这个文件

import '../lib/matchMedia.mock';
import { useMatchMedia } from '../lib/useMatchMedia';

describe('useMatchMedia()', () => {
  it('useMatchMedia() 被调用', () => {
    const res = useMatchMedia();
    expect(res).toBeDefined();
  });
});


从上面的例子大概就能理解基本上官方的意思了,具体如何使用,这个可以自己有发挥。

如果国内的用户还是不知道如何流畅的运行jest的话建议翻翻我前面的文章。
项目实践地址

https://github.com/durban89/webpack4-react16-reactrouter-demo.git
tag:v_1.0.29

上一篇:React 16 Jest ES6 Class Mocks(使用ES6语法类的模拟) 实例二


下一篇:年终总结