我正在尝试测试从React Native Button
元素调用组件方法。
由于某种原因,除非我同时做这些事情,否则测试失败。
wrapper.find(Button).first().props().onPress();
wrapper.find(Button).first().simulate('press');
如果我注释了其中两行,则测试失败,表明expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();
失败。
这是我的组成部分:
import React, { Component } from 'react';
import { Button, SafeAreaView, Text } from 'react-native';
import EmailPasswordModal from './EmailPasswordModal/EmailPasswordModal';
class Login extends Component {
state = {
emailPasswordModalVisible: false,
};
toggleEmailPasswordModal = () => {
console.log('TOGGLED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
const { emailPasswordModalVisible } = this.state;
this.setState({ emailPasswordModalVisible: !emailPasswordModalVisible });
};
render() {
const { emailPasswordModalVisible } = this.state;
return (
<SafeAreaView>
<EmailPasswordModal
visible={ emailPasswordModalVisible }
close={ this.toggleEmailPasswordModal }
/>
<Text>Login Screen!</Text>
<Button
onPress={ this.toggleEmailPasswordModal }
title="Login with Email and Password"
color="#841584"
accessibilityLabel="Login with Email and Password"
/>
</SafeAreaView>
);
}
}
export default Login;
这是我的考试:
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import { shallow } from 'enzyme';
import { Button } from 'react-native';
import Login from './Login';
describe('Login Screen', () => {
describe('Snapshot Tests', () => {
it('renders the screen with default state', () => {
const renderer = new ShallowRenderer();
const props = {};
renderer.render(<Login { ...props } />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
});
describe('Functional Tests', () => {
it('calls the toggleEmailPasswordModal method', () => {
const wrapper = shallow(<Login />);
const instance = wrapper.instance();
jest.spyOn(instance, 'toggleEmailPasswordModal');
wrapper.find(Button).first().props().onPress();
wrapper.find(Button).first().simulate('press');
expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();
});
});
});
奇怪的是,运行测试时,输出显示为“ TOGGLED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!“两次,因为已登录该组件。
但是,如果我将expect
更改为:
expect(instance.toggleEmailPasswordModal).toHaveBeenCalledTimes(1);
测试通过。
如果我将expect
更改为:
expect(instance.toggleEmailPasswordModal).toHaveBeenCalledTimes(2);
测试失败,原因是toggleEmailPasswordModal
仅被调用了1次。
为什么我同时需要这两个wrapper.find(Button)...
行?我从未见过其他任何需要同时使用它们的测试。
谢谢, 贾斯汀
我更新了我的测试,如下所示:
it('calls the toggleEmailPasswordModal method', () => {
const wrapper = shallow(<Login />);
const instance = wrapper.instance();
jest.spyOn(instance, 'toggleEmailPasswordModal');
wrapper.find(Button).first().props().onPress();
wrapper.find(Button).first().simulate('press');
expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();
// I ADDED THIS SECTION HERE
expect(instance.state.emailPasswordModalVisible).toBe(true);
});
由于instance.state.emailPasswordModalVisible = false
,测试失败。这很奇怪,因为显然调用了toggleEmailPasswordModal。但是,由于我怀疑它实际上被调用了两次,因此我对测试进行了如下更新:
it('calls the toggleEmailPasswordModal method', () => {
const wrapper = shallow(<Login />);
const instance = wrapper.instance();
jest.spyOn(instance, 'toggleEmailPasswordModal');
wrapper.find(Button).first().props().onPress();
// CHANGES START HERE
// wrapper.find(Button).first().simulate('press');
// expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();
expect(instance.state.emailPasswordModalVisible).toBe(true);
});
猜猜是什么?测试正确通过。因此,明确地两次调用wrapper.find...
函数实际上是两次调用toggleEmailPasswordModal
方法。那么,如果我不打两次电话,为什么它无法检测到它?为什么不正确地认为该方法仅被调用过一次?
答案 0 :(得分:0)
我终于有了答案。根据{{3}},我需要执行instance.forceUpdate()
才能将间谍附加到组件上。
it('calls the toggleEmailPasswordModal method', () => {
const wrapper = shallow(<Login />);
const instance = wrapper.instance();
const spy = jest.spyOn(instance, 'toggleEmailPasswordModal');
// This is added per https://stackoverflow.com/questions/44769404/jest-spyon-function-called/44778519#44778519
instance.forceUpdate();
wrapper.find(Button).first().props().onPress();
expect(spy).toHaveBeenCalledTimes(1);
expect(instance.state.emailPasswordModalVisible).toBe(true);
});
现在,测试通过了!