Напишите шутник для моего первого компонента - PullRequest
0 голосов
/ 11 июня 2018

Я только что закончил писать свой первый Reactjs компонент, и я готов написать несколько тестов (я использовал material-ui Table и Toggle).Я читал о jest и enzyme, но чувствую, что мне все еще что-то не хватает.

Мой компонент выглядит следующим образом (упрощенно):

export default class MyComponent extends Component {
    constructor() {
        super()
        this.state = {
            data: []
        }

        // bind methods to this
    }

    componentDidMount() {
        this.initializeData()
    }

    initializeData() {
        // fetch data from server and setStates
    }

    foo() {
        // manuipulatig data
    }

    render() {
        reutrn (
            <Toggle
                id="my-toggle"
                ...
                onToggle={this.foo}
            >
            </Toggle>

            <MyTable
                id="my-table"
                data={this.state.data}
                ...
            >
            </MyTable>
        )
    }
}

Теперь для теста.Я хочу написать тест для следующего сценария:

  1. Подарить initializeData с проверенными данными.
  2. Переключить my-toggle
  3. Утверждение данных изменилось (Должен ли я утверждатьсами данные или лучше вместо этого утверждать мою таблицу?)

Итак, я начал в самом начале с:

describe('myTestCase', () => {
    it('myFirstTest', () => {
        const wrapper = shallow(<MyComponent/>);
    }
})

Я запустил его, но он не удался:ReferenceError: fetch is not defined

Тогда мой первый вопрос: как мне посмеяться над initializeData, чтобы преодолеть необходимость вызова реального кода, использующего fetch?


Я последовал этому ответу: https://stackoverflow.com/a/48082419/2022010 и придумал следующее:

describe('myTestCase', () => {
    it('myFirstTest', () => {
        const spy = jest.spyOn(MyComponent.prototype, 'initializeData'
        const wrapper = mount(<MyComponent/>);
    }
})

Но я все еще получаю ту же ошибку (я также попробовал ее с componentDidMount вместо initializeData, новсе закончилось так же).


Обновление: Я был не прав.Я получаю ошибку извлечения не определено, но на этот раз она исходит из компонента Table (который является переносом для Table-UI).Теперь, когда я подумаю об этом, у меня есть много «уловок» на этом пути ... Интересно, как тогда позаботиться о них.

1 Ответ

0 голосов
/ 20 января 2019

fetch поддерживается в браузере, но шут / энзим выполняются в среде Node, поэтому fetch не является общедоступной функцией в вашем тестовом коде.Есть несколько способов обойти это:

1: глобально издеваться fetch - это, вероятно, самое простое решение, но, возможно, не самое чистое.

global.fetch = jest.fn().mockResolvedValue({
  json: () => /*Fake test data*/
  // or mock a response with `.text()` etc if that's what
  // your initializeData function uses
});

2: Аннотациявызов извлечения в сервисный уровень и внедрение этого в качестве зависимости - это сделает ваш код более гибким (хотя и более шаблонным), поскольку вы можете скрыть реализацию извлечения за любым интерфейсом, который вы выберете.Затем, в любой момент в будущем, если вы решите использовать другую библиотеку выборок, вы можете поменять реализацию на своем сервисном уровне.

// fetchService.js
export const fetchData = (url) => {
  // Simplified example, only takes 'url', doesn't
  // handle errors or other params.
  return fetch(url).then(res => res.json());
}

// MyComponent.js
import {fetchService} from './fetchService.js'

class MyComponent extends React.Component {
  static defaultProps = {
    // Pass in the imported fetchService by default. This
    // way you won't have to pass it in manually in production
    // but you have the option to pass it in for your tests
    fetchService
  }
  ...
  initializeData() {
    // Use the fetchService from props
    this.props.fetchService.fetchData('some/url').then(data => {
      this.setState({ data });
    })
  }
}

// MyComponent.jest.js
it('myFirstTest', () => {
  const fetchData = jest.fn().mockResolvedValue(/*Fake test data*/);
  const fetchService = { fetchData };
  const wrapper = mount(<MyComponent fetchService={fetchService} />);
  return Promise.resolve().then(() = {
    // The mock fetch will be resolved by this point, so you can make
    // expectations about your component post-initialization here
  })
}
...