Jest测试CSS module组件报错怎么办?

2,483 阅读2分钟

继上回讨论react-testing-library快速测试React组件渲染之后,你可能很快发现在实际使用当中遇到各种问题。比如这个:

因为在MyComponent.tsx中,引入了CSS Module:

import * as React from "react";
import * as s from "./styles.scss";

export default function MyComponent() {
  return <div className={s.container}>test</div>;
}

测试用例同一文中一样,并未做任何改动:

import * as React from "react";
import { render } from "@testing-library/react";
import MyComponent from "./MyComponent";

test("test render", () => {
  const { getByText } = render(<MyComponent />);
  expect(getByText("test")).toBeTruthy();
});

而且我的style.scss真实存在着:

.container {
  background: red;
}

那是怎么回事呢?

还记得你在打包工具如Webpack中配置的一系列loader吗?像:

import * as s from "./styles.scss";

这样的用法在JS文件中并不支持,能够这样使用是完全是因为loader在背后做了一系列工作,把这些语句“翻译”成了符合JS用法的语句。而测试框架并没有配置这样的loader,所以它在引入这段代码的时候会报错。

Jest支持一些类似loader的配置,让我们可以处理这样的情况。

用Jest transformer转换样式

Jest在错误提示中,提到了transform选项,它的默认值为;

{ "\\.[jt]sx?$": "babel-jest" }

transform可以在识别到import匹配模式的文件时用一个转义器(transformer)处理该文件的内容。以上默认值就是在匹配到后缀名为.js.jsx.ts.tsx的文件时用babel-jest转义。

针对CSS Module的转义器可以在npm上找到,如:jest-transform-css。安装后在jest.config.js添加以下配置来启用:

module.exports = {
  transform: {
    "\\.scss$": "jest-transform-css",
  },
}

保存配置,再重新执行测试就可以通过啦!

写个简单Jest mock跳过样式

还有一种方法是在不干扰测试结果的情况下,干脆用Jest mock工具跳过这些测试。

首先我们需要准备一个mock代码文件如__mocks__/fileMock.js:

module.exports = {};

然后告诉Jest遇到这些我需要识别的文件就直接找这个mock就好了。添加如下moduleNameMapper选项到jest.config.js:

module.exports = {
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|css|scss)$':
      '<rootDir>/__mocks__/fileMock.js',
  },
}

没错,这个方法还适用于其他任何不想识别的模块(不限于某种文件)。

保存配置,再重新执行测试就可以通过啦!

看看其他测试系列文:

加我微信