在jest 0.29中获取RN组件SplashScreen的generatePrivateKey方法实例
解决方案
针对React Native 0.70的SplashScreen组件在Jest 29中的测试问题,以下是两种可行的处理方式:
一、推荐:模拟用户交互测试(符合Testing Library理念)
Testing Library的核心是模拟真实用户操作,而非直接调用组件内部方法,这种方式更贴近实际场景,也避免耦合组件内部实现。
步骤说明:
- 修正navigation参数:原代码中传入的是返回navigation对象的函数,组件实际需要直接的navigation对象,需调整。
- 定位触发按钮:通过按钮的title属性找到"生成(新)密钥"按钮。
- 模拟点击并验证:触发点击事件后,验证方法调用或执行后的状态变化。
示例代码:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { render, screen, fireEvent, waitFor } from "@testing-library/react-native"; import SplashScreen from './SplashScreen'; // 监控组件内部方法,通过mock组件实现 jest.mock('./SplashScreen', () => { const OriginalSplashScreen = jest.requireActual('./SplashScreen').default; return { default: jest.fn((props) => { const component = OriginalSplashScreen(props); // 为可访问的内部方法添加spy if (component.generatePrivatekey) { component.generatePrivatekey = jest.fn(component.generatePrivatekey); } return component; }) }; }); describe('Splash screen when launching the app', () => { test('generate private key method shall work', async () => { // 修正navigation为直接对象 const navigation = { navigate: jest.fn() }; render( <NavigationContainer> <SplashScreen navigation={navigation} /> </NavigationContainer> ); // 定位触发按钮 const generateBtn = screen.getByTitle('生成(新)密钥'); // 模拟用户点击 fireEvent.press(generateBtn); // 验证方法被调用一次 await waitFor(() => { expect(SplashScreen.mock.results[0].value.generatePrivatekey).toHaveBeenCalledTimes(1); }); // 也可验证状态变化,比如按钮切换为"保存" // await waitFor(() => { // expect(screen.getByTitle('保存')).toBeTruthy(); // }); }); });
二、获取组件实例直接调用方法(不推荐,耦合内部实现)
如果确实需要直接访问组件内部方法,需根据组件类型做不同处理:
1. 类组件场景
类组件可通过测试实例直接获取组件对象,进而spy或调用方法:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { render, screen, fireEvent } from "@testing-library/react-native"; import SplashScreen from './SplashScreen'; describe('Splash screen when launching the app', () => { test('generate private key method shall work', () => { const navigation = { navigate: jest.fn() }; const wrapper = render( <NavigationContainer> <SplashScreen navigation={navigation} /> </NavigationContainer> ); // 获取组件实例 const splashInstance = wrapper.getByType(SplashScreen).instance; // Spy内部方法 const generateSpy = jest.spyOn(splashInstance, 'generatePrivatekey'); // 模拟点击触发方法 fireEvent.press(screen.getByTitle('生成(新)密钥')); expect(generateSpy).toHaveBeenCalledOnce(); }); });
2. 函数组件场景
函数组件没有实例,需通过forwardRef + useImperativeHandle暴露内部方法:
第一步:修改SplashScreen组件
import { forwardRef, useImperativeHandle } from 'react'; const SplashScreen = forwardRef((props, ref) => { const generatePrivatekey = () => { // 原方法逻辑 }; // 暴露方法给外部ref useImperativeHandle(ref, () => ({ generatePrivatekey })); // 原组件视图内容不变 return ( // ...你的组件视图代码 ); }); export default SplashScreen;
第二步:测试代码中获取ref并验证
import React, { useRef } from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { render, screen, fireEvent, waitFor } from "@testing-library/react-native"; import SplashScreen from './SplashScreen'; describe('Splash screen when launching the app', () => { test('generate private key method shall work', async () => { const navigation = { navigate: jest.fn() }; const splashRef = useRef(null); render( <NavigationContainer> <SplashScreen navigation={navigation} ref={splashRef} /> </NavigationContainer> ); // Spy暴露的方法 const generateSpy = jest.spyOn(splashRef.current, 'generatePrivatekey'); // 模拟点击触发方法 fireEvent.press(screen.getByTitle('生成(新)密钥')); await waitFor(() => { expect(generateSpy).toHaveBeenCalledOnce(); }); }); });
内容的提问来源于stack exchange,提问作者user938363
相关产品推荐
相关产品推荐

