Jest 和 Enzyme 的问题

Posted

技术标签:

【中文标题】Jest 和 Enzyme 的问题【英文标题】:Issue with Jest and Enzyme 【发布时间】:2020-01-15 13:14:31 【问题描述】:

我在使用 Jest 和 Enzyme 进行单元测试时遇到了一些问题。 我正在将 React 与 Typescript、情感框架一起使用。 我在按钮组件上添加了一个简单的单元测试,只是为了看看测试是否有效。

// button.test.tsx
import React from 'react'
import  shallow  from 'enzyme'
import  Button  from '../button'

describe('First React component test with Enzyme', () => 
  it('renders without crashing', () => 
    shallow(<Button/>);
  )
)
// button.tsx
import React from 'react'
import  FunctionComponent, htmlAttributes, ButtonHTMLAttributes  from 'react'
import  Icon  from '~/components'
import  styles  from './styles'

interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> 
  onClick?: () => any

  icon?: string
  color?: 'default' | 'accent' | 'accent-dark' | 'dark'
  size?: 'small' | 'medium' | 'big' | 'large'
  iconSize?: number
  withShadow?: boolean


export const Button: FunctionComponent<ButtonProps> = (
  onClick,
  color = 'default',
  size = 'medium',
  icon,
  withShadow,
  children,
  ...props
) => (
  <button
    css=[
      styles.base,
      styles.colors[color],
      styles.sizes[size],
      withShadow && styles.withShadow,
    ]
    onClick=onClick
    ...props
  >
    icon && (
      <span css=styles.icon[color === 'dark' ? 'dark' : 'default']>
        <Icon icon=icon size=color === 'dark' ? 16 : 12 />
      </span>
    )
    children
  </button>
)

并且报错如下:

● Test suite failed to run

    ReferenceError: localStorage is not defined

      12 | 
      13 |   constructor() 
    > 14 |     this.token = localStorage.getItem('token') || null
         |                  ^
      15 | 
      16 |     if (this.token) 
      17 |       this.profile = this.decodeToken(this.token)

      at new UserStore (src/stores/user.ts:14:18)
      at Object.<anonymous> (src/stores/index.ts:4:26)
      at Object.<anonymous> (src/components/header/index.tsx:5:1)

我使用 "jsx":"preserve" 作为构建的 typescript 编译选项,使用 "jsx":"react" 作为 jest 的 typescript 编译选项。

// tsConfig.js

  "compilerOptions": 
    "target": "esnext",
    "module": "esnext",
    "lib": ["esnext", "dom"],
    "jsx": "preserve",
    "types": ["@emotion/core", "@types/node", "jest"],

    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,

    "baseUrl": "./",
    "paths": 
      "~/*": ["src/*"]
    
  ,
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "include": ["src"]

这是开玩笑的配置:

// jestConfig.js

module.exports = 
  preset: 'ts-jest',
  testEnvironment: 'node',
  testMatch: ['**/src/**/*.test.ts?(x)', '**/?(*.)+(test).ts?(x)'],
  moduleNameMapper: 
    '\\.(jpg|jpeg|png|svg|ttf|woff|woff2)$':
      '<rootDir>/asset-transformer.js',
    '~(.*)$': '<rootDir>/src/$1'
  ,
  globals: 
    'ts-jest': 
      tsConfig: 
        jsx: "react"
      
    
  ,
  snapshotSerializers: [
      "enzyme-to-json/serializer"
    ],
    setupFiles: [
      "./test-shim.js",
      "./test-setup.js"
    ],
    moduleFileExtensions: [
      "ts",
      "tsx",
      "js",
      "jsx"
    ],
    transform: 
      "^.+\\.js(x)$": "babel-jest",
      "^.+\\.(ts|tsx)$": "./test-preprocessor.js"
    ,
    testMatch: [
      "**/*.test.(ts|tsx|js|jsx)"
    ]

// .babel.rc

  "plugins": [
    [
      "transform-inline-environment-variables"
    ],
    [
      "babel-plugin-jsx-pragmatic",
      
        "export": "jsx",
        "module": "@emotion/core",
        "import": "___EmotionJSX"
      
    ],
    [
      "@babel/plugin-transform-react-jsx",
      
        "pragma": "___EmotionJSX",
        "pragmaFrag": "React.Fragment"
      
    ],
    [
      "emotion",
      
        "sourceMap": true,
        "autoLabel": false,
        "cssPropOptimization": true
      
    ],
    [
      "@babel/plugin-syntax-dynamic-import"
    ]
  ],
  "presets": [
    [
      "@babel/preset-env",
      
        "modules": false,
        "targets": 
          "node": "current"
        
      
    ],
    "@babel/preset-typescript"
  ],

【问题讨论】:

【参考方案1】:

有几种方法可以解决这个问题,但我们的想法是利用模拟/间谍。

1) 窥探localStorage 的原型。在github上讨论过这个问题。

jest.spyOn(window.localStorage.__proto__, 'setItem');

2) 模拟 localStorage 本身的方法。 *** 上的另一个 post 充分涵盖了它们。

【讨论】:

我尝试了所有这些,但我只测试了一个组件 - button,它不需要 localStorage。我认为这是配置的问题。谢谢。

以上是关于Jest 和 Enzyme 的问题的主要内容,如果未能解决你的问题,请参考以下文章

React / Enzyme:运行 Jest / Enzyme 测试时出现 Invariant Violation 错误

使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件

用 Jest 和 Enzyme 测试 React Router

异步 componentDidMount 时使用 React 的 Jest 和 Enzyme 进行测试

设置 Jest 和 Enzyme 来测试 React 15 找不到模块 react/lib/ReactTestUtils

Jest、Enzyme 和 Styled Component 不适用于警告:React.createElement