Как смоделировать класс обслуживания AuthService, используемый в компоненте для тестирования? - PullRequest
0 голосов
/ 07 ноября 2019

Как в классе, так и в функциональных компонентах у меня есть импортируемый AuthService с методом выборки (который я использую вместо global.fetch).

В моих тестовых файлах я пытаюсь смоделироватьэтот AuthService, чтобы я мог протестировать TestComponent, но TestComponent использует реализацию по умолчанию. Это экземпляр фактического экземпляра AuthService. Как я могу издеваться над этим классом обслуживания? Например:

//AuthService.js

export default class AuthService {
    constructor() {
        this.fetch = this.fetch.bind(this);
    }
    fetch() {
        return fetch(url).then((res) => {
            return res.json();
        })
    }
}

//Tester.js
import AuthService from '/path/to/auth';
import { useState, useEffect } from 'react';

export default Tester = () => {
    const Auth = new AuthService();
    const [thing, setThing] = useState('')
    useEffect(() => {
        Auth.fetch('url').then((data) => {
            setThing(data)
        })
    })
    return (
        <p>{thing}</p>);

}

//Tester.spec.js
import AuthService from '/path/to/auth';
import Tester from '/path/to/tester';
it('<Test>', () => {
    const component = shallow(<Tester />);
    const mockFetch = jest.fn(() => Promise.resolve('newResult'))
    jest.mock('path/to/auth', () => () => ({

        fetch: mockFetch

    }));
    expect(component.find('p').text()).toEqual('');
    component.update();
    expect(component.find('p').text()).toEqual('newResult');

})

1 Ответ

1 голос
/ 07 ноября 2019

Во-первых, я думаю, что эффект Auth.fetch нужно запустить один раз. В документах написано :

Пустой набор зависимостей [] означает, что эффект будет запускаться только один раз, когда компонент монтируется, а не при каждом повторном рендеринге.

Итак, вам нужно передать пустой [] в качестве второго параметра для useEffect.

Вот решение для модульного теста при использовании useEffect и enzyme

AuthService.js:

export default class AuthService {
  constructor() {
    this.fetch = this.fetch.bind(this);
  }
  fetch(url) {
    return fetch(url).then(res => {
      return res.json();
    });
  }
}

Tester.jsx:

import AuthService from './AuthService';
import React, { useState, useEffect } from 'react';

export default () => {
  const Auth = new AuthService();
  const [thing, setThing] = useState('');
  useEffect(() => {
    console.count('useEffect');
    Auth.fetch('url').then(data => {
      setThing(data);
    });
  }, []);
  return <p>{thing}</p>;
};

Tester.spec.jsx:

import React from 'react';
import { mount } from 'enzyme';
import AuthService from './AuthService';
import Tester from './Tester';
import { act } from 'react-dom/test-utils';

jest.mock('./AuthService', () => {
  const mAuthService = {
    fetch: jest.fn()
  };
  return jest.fn(() => mAuthService);
});

it('<Test>', async () => {
  const authService = new AuthService();
  authService.fetch.mockResolvedValue('newResult');
  const component = mount(<Tester />);
  expect(component.find('p').text()).toEqual('');
  await act(async () => {
    await new Promise(resolve => setTimeout(resolve, 0));
  });
  expect(component.find('p').text()).toEqual('newResult');
});

Результат модульного теста со 100% покрытием:

 PASS  src/stackoverflow/58741410/Tester.spec.jsx
  ✓ <Test> (64ms)

  console.count src/stackoverflow/58741410/Tester.jsx:858
    useEffect: 1

------------|----------|----------|----------|----------|-------------------|
File        |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------|----------|----------|----------|----------|-------------------|
All files   |      100 |      100 |      100 |      100 |                   |
 Tester.jsx |      100 |      100 |      100 |      100 |                   |
------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.834s, estimated 14s

Версии зависимостей:

"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"jest": "^24.9.0",
"jest-environment-enzyme": "^7.1.1",
"jest-enzyme": "^7.1.1",
"react": "^16.11.0",
"react-dom": "^16.11.0",

Исходный код: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58741410

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...