Я пытаюсь протестировать этот блок кода в своем приложении React с помощью Jest и Enzyme:
openDeleteUserModal = ({ row }: { row: IUser | null }): any => (
event: React.SyntheticEvent
): void => {
if (event) event.preventDefault();
this.setState({ userToDelete: row, isDeleteUserModalOpen: true });
};
Это тест:
describe('OpenDeleteUserModal', () => {
let wrapper: ReactWrapper;
let instance: any;
beforeEach(() => {
wrapper = mount(
<MemoryRouter>
<Route render = {props => <UsersOverviewScreen {...props} {...defaultProps} />} />
</MemoryRouter>
);
instance = getComponentInstance(wrapper);
instance.openDeleteUserModal({ user: mockUser });
wrapper.update();
});
it('should SET the isDeleteUserModalOpen to true', () => {
expect(instance.state.isDeleteUserModalOpen).toBeTruthy();
});
it('should SET the userToDelete to mockUser', () => {
expect(instance.state.userToDelete).toEqual(mockUser);
});
});
Тест и файл имеют .tsx
, что означает, что необходим весь шаблон, касающийся React Router. Я получаю обратно false и undefined вместо true.
Я пытался имитировать щелчок, но безуспешно. Смотри ниже:
it('should SET the isDeleteUserModalOpen to true', () => {
const deleteUserButton = wrapper.find('renderUsers').find('button');
deleteUserButton.simulate('click');
jest.spyOn(instance, 'openDeleteUserModal');
instance.openDeleteUserModal();
expect(instance.openDeleteUserModal).toHaveBeenCalled();
expect(instance.state.isDeleteUserModalOpen).toBeTruthy();
});
Может кто-нибудь помочь мне понять, почему это не удается.
{Expected: true, Received: false}, for the first test. {Expected: MockUser, Recieved: undefined}
. Это ошибка, которую я получаю с решением, которое я пробовал, или без него. Кажется, событие click не происходит.
Я думал об удалении preventDefault
из фактической функции. Это решило бы проблему, но тогда состояние бардак. Нужно разобраться.
Я просматривал энзим github образцы ферментных тестов. Попробуйте это
describe('OpenDeleteUserModal', () => {
let wrapper: ReactWrapper;
let instance: any;
beforeEach(() => {
wrapper = mount(
<MemoryRouter>
<Route render = {props => <UsersOverviewScreen {...props} {...defaultProps} />} />
</MemoryRouter>
);
instance = getComponentInstance(wrapper);
instance.openDeleteUserModal({ user: mockUser });
// wrapper.update(); --don't think this is required but do check!
});
it('should SET the isDeleteUserModalOpen to true', () => {
//expect(instance.state.isDeleteUserModalOpen).toBeTruthy();
expect(wrapper.state('isDeleteUserModalOpen')).toBeTruthy();
});
it('should SET the userToDelete to mockUser', () => {
//expect(instance.state.userToDelete).toEqual(mockUser);
expect(wrapper.state('userToDelete')).toEqual(mockUser);
});
});
This is most probably because setState() is an async operation. When your test line runs the relevant state might not have been initialized. Enzyme seems to have provided an API for this.
Для второй части это небольшая оговорка в Enzyme при тестировании стрелочных функций. Проверьте мой ответ здесь. Следующий код должен решить вашу проблему.
it('should SET the isDeleteUserModalOpen to true', () => {
const deleteUserButton = wrapper.find('renderUsers').find('button');
deleteUserButton.simulate('click');
//this returns an object which will record interactions on 'openDeleteUserModal'
const spy = jest.spyOn(instance, 'openDeleteUserModal');
//Force update on the component is required for the spy to 'latch onto' an arrow function
instance.forceUpdate();
instance.openDeleteUserModal();
//You have to check your spy object not the instance method
expect(spy).toHaveBeenCalled();
expect(instance.state('isDeleteUserModalOpen')).toBeTruthy();
});
Спасибо. Но это только часть решения. Мой OpenDeleteUserModal
- это метод (функция внутри другой функции). Таким образом, он не вызывал вторую функцию, чтобы проверить данные, а вызов..
@DimitrisEfst Проверьте это сейчас
Я сделал еще несколько изменений.
Глядя на это несколько лет спустя. Спасибо за ваше объяснение. Но разве использование instance.state не считается анти-шаблоном? Из того, что я вижу в документах, они просят вас использовать оболочку для доступа к значениям состояния.
Однако я пришел сюда в поисках решения, если ответы не сработали для меня. Проконсультировавшись с документом Enzyme, я обнаружил, что setState() отлично работает для меня. Ниже приведено мое решение с setState(), нам не нужно вызывать Обновлять(), так как setState() повторно отображает компонент.
describe('OpenDeleteUserModal', () => {
let wrapper: ReactWrapper;
let instance: any;
beforeEach(() => {
wrapper = mount(
<MemoryRouter>
<Route render = {props => <UsersOverviewScreen {...props} {...defaultProps} />} />
</MemoryRouter>
);
});
it('should SET the isDeleteUserModalOpen to true', () => {
expect(wrapper.setState({isDeleteUserModalOpen: true}).toBeTruthy();
});
it('should SET the userToDelete to mockUser', () => {
expect(wrapper.setState({userToDelete: mockUser})).toEqual(mockUser);
});
});
Можете поделиться журналом ошибок?