Enzyme模拟React Native中BorderlessButton点击不生效的问题解决
Let's break down why your final test case isn't working and fix it step by step.
Root Causes of the Issue
- Unused Mock Function: Your
mockOnPressis defined but never connected to the component's button behavior. The button in your component uses the internalhandleNextmethod, not a prop-based onPress function, so this mock was irrelevant to the test. - Incorrect Event Simulation: React Native buttons use the
pressevent, notclick—your original test usedsimulate('click')which won't trigger the onPress handler. - Potential Button Disabling: Your
disableButtonlogic might leave the button in a disabled state (even if unintentionally), which blocks press events from firing. - Wrong Assertion Target: You were checking if an unused mock was called, instead of verifying the actual behavior triggered by the button press (navigation to
PreferredName).
Step-by-Step Fixes
1. Mock the Navigation Service
The handleNext method calls navigationService.navigate('PreferredName'), so we need to mock this service to verify the navigation action. Add this at the top of your test file (adjust the import path to match your project):
// Mock the navigation service used in the component jest.mock('../path/to/navigationService', () => ({ navigate: jest.fn() })); import navigationService from '../path/to/navigationService';
2. Ensure the Button is Enabled
Update your mock props to guarantee disableButton returns a falsy value. Your existing errors: null should work, but let's make sure the props cover all cases the component checks:
const mockProps: any = { errors: null, values: [{ givenName: 'givenName', familyName: 'familyName' }], step: 1, // Add required step prop for ProgressBar resetForm: jest.fn() // Add missing resetForm prop to avoid errors };
3. Fix the Test Case
Replace the broken test with one that simulates the correct event and asserts the right behavior:
it('should trigger navigation to PreferredName when NEXT button is pressed', () => { // First verify the button is not disabled expect(wrapper.find(BorderlessButton).props().disabled).toBeFalsy(); // Simulate the correct React Native press event wrapper.find(BorderlessButton).simulate('press'); // Assert the navigation action was triggered expect(navigationService.navigate).toHaveBeenCalledWith('PreferredName'); });
4. Clean Up Mocks Between Tests
Add jest.clearAllMocks() to your beforeEach to ensure mocks don't retain calls between test cases, keeping results consistent.
Full Corrected Test Code
import { shallow } from 'enzyme'; import React from 'react'; import { BorderlessButton, InputBox, ProgressBar } from 'components'; import Name from '../name.component'; // Mock navigation service jest.mock('../path/to/navigationService', () => ({ navigate: jest.fn() })); import navigationService from '../path/to/navigationService'; describe('Name component', () => { let wrapper: any; const mockSaveStep = jest.fn(); const mockProps: any = { errors: null, values: [{ givenName: 'givenName', familyName: 'familyName' }], step: 1, resetForm: jest.fn() }; beforeEach(() => { wrapper = shallow(<Name signUpForm={mockProps} saveStep={mockSaveStep} />); jest.clearAllMocks(); // Reset mocks before each test }); it('should render Name component', () => { expect(wrapper).toMatchSnapshot(); }); it('should render 2 <InputBox />', () => { expect(wrapper.find(InputBox)).toHaveLength(2); }); it('should render a <ProgressBar />', () => { expect(wrapper.find(ProgressBar)).toHaveLength(1); }); it('should render a <BorderlessButton /> with the text NEXT', () => { expect(wrapper.find(BorderlessButton)).toHaveLength(1); expect(wrapper.find(BorderlessButton).props().text).toEqual('NEXT'); }); it('should trigger navigation to PreferredName when NEXT button is pressed', () => { expect(wrapper.find(BorderlessButton).props().disabled).toBeFalsy(); wrapper.find(BorderlessButton).simulate('press'); expect(navigationService.navigate).toHaveBeenCalledWith('PreferredName'); }); });
内容的提问来源于stack exchange,提问作者Shashika Virajh

