Таким образом, тест должен обеспечить ввод для функции и проверить вывод. С React вход для функции может исходить либо от props
, либо от дочернего компонента / функции. Хорошо, есть и другие способы, но сейчас давайте посмотрим на эти два пути.
У меня есть компонент Container, который выполняет некоторую бизнес-логику и отображает дочерний элемент:
import React, { useEffect } from 'react'
import ExampleView from './ExampleView'
const ExampleContainer = ({ onSomeBusinessDone, iHaveMounted }) => {
useEffect(() => {
// An example of a "on mount" style effect that we may need to test
// Grab data, do some initial logic whatever, but test that I call a prop
// within this mount call
iHaveMounted()
}, [])
const onDoSomeBussinessLogic = (eventData = {}) => {
// Do something with the data perhaps
eventData.whoa = true
onSomeBusinessDone(eventData)
}
return <ExampleView onSomething={onDoSomeBussinessLogic} />
}
export default ExampleContainer
Этот контейнер обеспечивает стиль обратного вызова prop
для дочернего элемента. Цель состоит в том, чтобы проверить, что, когда дочерний элемент вызывает эту функцию, Контейнер что-то с ней делает, а затем вызывает свой собственный стиль обратного вызова (или выход, который мы хотели бы проверить).
Проблема, с которой я сталкиваюсь, состоит в том, как вызвать эту функцию, которая предоставляется ребенку в Jest / React с помощью хуков?
Настройки немного сложно объяснить словами, но у меня есть репозиторий и коды:
https://github.com/Kikketer/hooks-test-questions
https://codesandbox.io/embed/hooks-tests-questions-vvrv6
Песочницу лучше всего смотреть, но я не мог понять, как запустить там шутку, поэтому было бы проще всего попробовать ее после клонирования.
Здесь есть пара вещей:
- Я не могу использовать неглубокое средство визуализации, поскольку мне также нужно проверить, что
useEffect
перехватчики также вызывают свойство.
- Я использую макет рендеринга дочернего компонента в функции Container, чтобы он не пытался рендерить дочерний компонент, так как я только тестирую контейнер, и мне не нужно беспокоиться о зависимостях или других ошибках этого дочернего элемента. Только что я передаю полезные и ожидаемые реквизиты.
Мой тест выглядит так:
jest.mock('./ExampleView', () => props => <div data-id="ExampleView" {...props} />)
...
...
test('when a child does something expect the prop function to have `whoa`', () => {
const onSomething = jest.fn()
act(() => {
renderer.create(<ExampleContainer onSomething={onSomething} />)
})
// Somehow trigger the child's action... not sure how
// Urm....
expect(onSomething).toHaveBeenCalledWith({ clicked: true, whoa: true })
})
Опять я высмеиваю вид, потому что я не могу использовать неглубокое средство визуализации и не хочу отображать детей. Я просто хочу проверить реквизит (что делает снимок красиво).
Как я это сделал, используя класс
До хуков я мог бы добраться до компонента и напрямую вызвать функцию:
const onSomeBusinessDone = jest.fn()
const iHaveMounted = jest.fn()
const component = new ExampleContainer({onSomeBusinessDone, iHaveMounted})
component.onDoSomeBussinessLogic({clicked: true})
// I can check to see that given the input (clicked) I get the output:
expect(onSomeBusinessDone).toHaveBeenCalledWith({clicked: true, whoa: true})
Я понимаю, что создание реактивного компонента new
не одобряется, но это позволило бы мне довольно просто выполнить этот тест. Я не верю, что смогу сделать подобный формат с Hooks, потому что это функция, которая не раскрывает внутренние функции.