首页 > 解决方案 > 如何在进行单元测试时调用 React 组件的自定义方法。我正在使用打字稿

问题描述

我正在使用对打字稿做出反应。谁能告诉我如何调用在单元测试中的组件中编写的自定义方法。

我试过了shallowmount但我无法调用自定义方法。

import React  from 'react';
import {
  Theme,
  withStyles,
  createStyles,
} from '@material-ui/core';

export interface IFileUploadProps{}
export interface IFileUploadState {}

const styles = (theme: Theme) => {
  return createStyles({
    root: {
      paddingTop: theme.spacing(2),
      paddingBottom: theme.spacing(2),
      width: '100%',
      backgroundColor: 'inherit',
    },
    input: {
      display: 'none',
    },
    padding24: {
      paddingLeft: theme.spacing(3),
      paddingRight: theme.spacing(3),
    },
  });
};

class FileUpload extends React.Component<IFileUploadProps, IFileUploadState> {

    validateImage = () => {
      console.log('validate image');
    }

    render() {
      return <div>file upload</div>;
    }
  }

export default withStyles(styles)(FileUpload);

我需要做这样的事情。

import React from 'react';
import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16'
import FileUpload from './FileUpload';

configure({ adapter: new Adapter() });   
describe('FileUpload', () => {
  test('should call validateImage method correctly', () => {
    const wrapper = shallow(<FileUpload ></FileUpload>);
    wrapper.instance()['validateImage']();
  });
});

在这里我收到错误。

TypeError:无法读取 null 的属性“validateImage”

当我使用“export default withStyles(styles)(FileUpload);”导出文件时发生此错误 当我使用导出默认 FileUpload 时,它工作正常。

标签: reactjstypescriptunit-testingjestjsenzyme

解决方案


它应该工作。例如:

FileUpload.tsx

import React from 'react';

interface IFileUploadProps {}
interface IFileUploadState {}

export class FileUpload extends React.Component<IFileUploadProps, IFileUploadState> {
  validateImage() {
    console.log('validate image');
  }

  render() {
    return <div>file upload</div>;
  }
}

FileUpload.spec.tsx

import React from 'react';
import { shallow } from 'enzyme';
import { FileUpload } from './FileUpload';

describe('FileUpload', () => {
  test('should call validateImage method correctly', () => {
    const logSpy = jest.spyOn(console, 'log');
    const wrapper = shallow(<FileUpload></FileUpload>);
    expect(wrapper.text()).toBe('file upload');
    // @ts-ignore
    // tslint:disable-next-line: no-string-literal
    wrapper.instance()['validateImage']();
    expect(logSpy).toBeCalledWith('validate image');
  });
});

100% 覆盖率的单元测试结果

 PASS  src/stackoverflow/58642342/FileUpload.spec.tsx
  FileUpload
    ✓ should call validateImage method correctly (14ms)

  console.log node_modules/jest-mock/build/index.js:860
    validate image

----------------|----------|----------|----------|----------|-------------------|
File            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files       |      100 |      100 |      100 |      100 |                   |
 FileUpload.tsx |      100 |      100 |      100 |      100 |                   |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.487s, estimated 9s

更新 1

strict: true您应该在tsconfig.json文件中禁用。或者,用于// @ts-ignore跳过 tsc 的静态类型检查。

更新 2

由于您使用 HOC -withStyles高阶函数,因此您需要使用.dive([options]) => ShallowWrapper方法enzyme来获取FileUpload组件的浅包装。

FileUpload.tsx

import React from 'react';
import { Theme, withStyles, createStyles } from '@material-ui/core';

interface IFileUploadProps {}
interface IFileUploadState {}

const styles = (theme: Theme) => {
  return createStyles({
    root: {
      paddingTop: theme.spacing(2),
      paddingBottom: theme.spacing(2),
      width: '100%',
      backgroundColor: 'inherit'
    },
    input: {
      display: 'none'
    },
    padding24: {
      paddingLeft: theme.spacing(3),
      paddingRight: theme.spacing(3)
    }
  });
};

class FileUpload extends React.Component<IFileUploadProps, IFileUploadState> {
  validateImage() {
    console.log('validate image');
  }

  render() {
    return <div>file upload</div>;
  }
}

export default withStyles(styles)(FileUpload);

FileUpload.spec.tsx

import React from 'react';
import { shallow } from 'enzyme';
import FileUpload from './FileUpload';

describe('FileUpload', () => {
  test('should call validateImage method correctly', () => {
    const logSpy = jest.spyOn(console, 'log');
    const wrapper = shallow(<FileUpload></FileUpload>);
    expect(wrapper.dive().text()).toBe('file upload');
    // @ts-ignore
    // tslint:disable-next-line: no-string-literal
    wrapper
      .dive()
      .instance()
      ['validateImage']();
    expect(logSpy).toBeCalledWith('validate image');
  });
});

覆盖率 100% 的单元测试结果:

 PASS  src/stackoverflow/58642342/FileUpload.spec.tsx
  FileUpload
    ✓ should call validateImage method correctly (31ms)

  console.log node_modules/jest-mock/build/index.js:860
    validate image

----------------|----------|----------|----------|----------|-------------------|
File            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files       |      100 |      100 |      100 |      100 |                   |
 FileUpload.tsx |      100 |      100 |      100 |      100 |                   |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.517s, estimated 12s

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58642342


推荐阅读