Как использовать jest.spyOn с компонентом функции React с использованием Typescript
Я разрабатываю приложение React с использованием Typescript и хуков, и я пытаюсь использовать Enzyme с Jest для тестирования компонентов функций. Я не могу использовать jest.spyOn для тестирования метода в моем компоненте. Метод jest.spyOn не разрешается правильно и показывает следующее сообщение при наведении
"Аргумент типа" validateBeforeSave"не может быть назначен параметру типа"context" | "setState" | "forceUpdate" | "render" | "componentDidMount" | "shouldComponentUpdate" | "componentWillUnmount" | "componentDidCatch" | "getSnapshotBeforeUpdate" | ... еще 6... | "UNSAFE_componentWillUpdate"'.ts(2345)"
Я пытался разыграть экземпляр как "Любой" -
const instance = wrapper.instance() as any;
Это, конечно, игнорирует проблему во время компиляции, но затем тест выдает ошибку времени выполнения, что функция не существует в компоненте.
Невозможно следить за свойством validateBeforeSave, поскольку оно не является функцией; вместо этого дано неопределенное
// Some function Component
const SomeComponent = (props: IMyComponentProps) => {
const { classes } = props;
// Component has state
const [count, setCount] = useState(0);
function validateBeforeSave(){
}
function handleClick() {
validateBeforeSave();
.
.
.
}
return (
<div>
<Button>
className="saveBtn"
onClick={handleClick}
</Button>
</div>
);
};
// Unit test
describe('SomeComponent' () => {
it('validates model on button click', () => {
const wrapper = mount(
<MuiThemeProvider theme={theme}>
<SomeComponent/>
</MuiThemeProvider>,
);
const instance = wrapper.instance();
const spy = jest.spyOn(instance, "validateBeforeSave");
wrapper
.find('.saveBtn')
.at(0)
.simulate('click');
expect(spy).toHaveBeenCalledTimes(1);
});
}
Что мне здесь не хватает? Как spyOn работает с функциональными компонентами?
Я создал приложение с помощью шаблона create-реагировать на приложение, и оно имеет эти зависимости для тестовых пакетов
"devDependencies": {
"ts-jest": "^23.10.3",
"@types/jest": "24.0.9",
"@types/enzyme": "^3.9.1",
"@types/enzyme-adapter-react-16": "^1.0.2",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.11.2",
"enzyme-to-json": "^3.3.5",
}
3 ответа
Публикация моего комментария здесь снова, чтобы ответить на ваш вопрос: Ваш validateBeforeSave
функция объявлена в SomeComponent
делая его закрытой / закрытой областью, недоступной снаружи. Вы можете передать эту функцию в качестве реквизита, а затем создать шпиона и передать его в качестве значения реквизита в своем тесте и проверить, была ли вызвана пропущенная функция (шпион) или нет.
Таким образом, вы бы изменили свою функцию примерно так:
// some validator function
function validateBeforeSave(){
...
}
// Some function Component
const SomeComponent = (props: IMyComponentProps) => {
const { classes, validateBeforeSave } = props;
// Component has state
const [count, setCount] = useState(0);
function handleClick() {
validateBeforeSave();
.
.
.
}
return (
<div>
<Button>
className="saveBtn"
onClick={handleClick}
</Button>
</div>
);
};
И в вашем модульном тесте, что-то вроде этого:
// Unit test
describe('SomeComponent' () => {
it('validates model on button click', () => {
const validateSpy = jest.fn();
const wrapper = mount(
<MuiThemeProvider theme={theme}>
<SomeComponent validateSpy={validateSpy}/>
</MuiThemeProvider>,
);
const instance = wrapper.instance();
wrapper
.find('.saveBtn')
.at(0)
.simulate('click');
expect(validateSpy).toHaveBeenCalledTimes(1);
});
}
Я также столкнулся с той же проблемой - мне понравилось ниже -
import * as React from 'react';
const SampleComponent = () => {
const sampleMethod = () => {
console.log('hello world');
};
return <button onClick={sampleMethod} type="button">Click Me</button>;
};
export default SampleComponent;
контрольная работа -
import React from 'react';
import SampleComponent from './';
import { shallow } from 'enzyme';
describe('SampleComponent', () => {
test('should handle click correctly', () => {
const logSpy = jest.spyOn(console, 'log');
const wrapper = shallow(<SampleComponent></SampleComponent>);
const button = wrapper.find('button');
expect(button.text()).toBe('Click Me');
button.simulate('click');
expect(logSpy).toBeCalledWith('hello world');
});
});
Мы можем шпионить за console.log, чтобы утверждать, что он должен вызываться или нет
У меня была аналогичная проблема с имитацией метода обратного вызова с React 16.xx, метод экземпляра фермента возвращает значение null, что вы можете сделать, это передать напрямую jest.fn() в качестве опоры.
ПРИМЕР:
it('should invoke callback with proper data upon checkbox click', () => {
const spyCheckboxClick = jest.fn((id, item) => ({
id,
item,
}))
const component: any = enzyme.mount(
<SectionColumn {...{
...mockProps,
onCheckboxClick: spyCheckboxClick,
}} />
);
expect(spyCheckboxClick).toHaveBeenCalledTimes(0);
// perform click to checkbox
const checkboxComponent = component.find('StyledCheckbox');
const input = checkboxComponent.first().children();
input.simulate('change');
expect(spyCheckboxClick).toHaveBeenCalledTimes(1);
expect(spyCheckboxClick()).toEqual(null)
});