用 jest 结合 @testing-library/react 测试 react 组件时,由于组件内部 import 了 css 文件,会抛出如下错误
这是由于 jest 默认只识别 js/json文件,对 css/less 等文件,对该文件类型导入没有办法处理。当然不仅仅是 css/less 文件,除上述文件类型之外也是一样的。
解决的办法是使用 jest 的 moduleNameMapper
配置,将 css 文件映射为一个空对象,这样 jest 在处理 css 等不能识别的文件时就不会报错了。
moduleNameMapper
jest 提供了 moduleNameMapper
配置项,可以把模块映射到指定的模块。我们只需要把带有 css/less 等后缀的文件映射到一个空对象即可。
module.exports = {
moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
}
};
接下来在 __mocks__ 目录下新建一个 styleMock.js 文件,内容如下:
module.exports = {};
配置完,再次 pnpm run test
后,即可正常运行单测了。
不过还没完,大部分在开发react组件库的时候,我们使用 css module 的方式来应用样式,用于减少样式命名冲突。然而如果配置成上述的方式,则无法使用 css 选择器来进行查找,因为 jest 在处理 css 变成了一个空对象,所以相当于没有引入样式。
举个例子,我们有一个组件 Button,样式文件 index.module.css,内容如下:
.button {
background-color: red;
}
在 Button 组件中引入样式文件:
import styles from './index.module.css';
const Button = () => {
return <button className={styles.button}>Click me</button>;
};
export default Button;
这样在对 Button 组件进行单测时,实际在内存中渲染的 Button 是这样的:
<button className="undefined">Click me</button>
这样就无法通过 css 选择器来查找到对应的元素了。
更优的方案
更优的方案是使用 identity-obj-proxy 这个库,该库会将 css/less 文件映射为一个对象,这样 jest 在处理 css 等文件,会将其转换为一个对象,更方便我们编写单元测试。
在项目中安装 identity-obj-proxy:
pnpm add identity-obj-proxy -D
修改 jest.config.js 配置如下:
module.exports = {
// ...其他配置
moduleNameMapper: {
'\\.(css|less)$': 'identity-obj-proxy'
}
};
这样配置后,上述的 Button 组件在内存中渲染的 Button 就是这样的:
<button className="button">Click me</button>
最后就可以使用 querySelector
,querySelectorAll
类似的 api 来查找元素。