如何在React Native中使用Detox mock函数 适配谷歌登录等场景测试
实现方案
1. Detox Mock 依赖前置配置
Detox的端到端测试mock基于Metro模块替换实现,需要先做如下配置:
- 项目根目录创建
e2e/mocks文件夹用于存放所有mock文件 - 修改
metro.config.js,添加环境变量判断逻辑,测试环境下将真实依赖替换为mock文件:
const defaultConfig = require('metro-config/src/defaults/defaults'); const path = require('path'); const isDetoxTest = process.env.DETOX_TEST === 'true'; module.exports = { resolver: { extraNodeModules: isDetoxTest ? { '@react-native-google-signin/google-signin': path.resolve(__dirname, 'e2e/mocks/@react-native-google-signin/google-signin.js'), // 替换为你项目中实际封装的AWS请求工具的mock路径 'src/utils/aws-request': path.resolve(__dirname, 'e2e/mocks/src/utils/aws-request.js'), } : {}, }, transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }), }, };
- 运行Detox测试前先设置环境变量,打包命令调整为
DETOX_TEST=true detox build -c android.emu.debug
2. 谷歌登录Mock实现
在e2e/mocks/@react-native-google-signin/google-signin.js中写入mock逻辑,返回固定测试用户数据:
export const GoogleSignin = { configure: jest.fn(), signIn: jest.fn(() => Promise.resolve({ user: { id: 'test-user-123', email: 'test@example.com', name: '测试用户', photo: 'https://example.com/avatar.png' } })), signOut: jest.fn(() => Promise.resolve()), getCurrentUser: jest.fn(() => Promise.resolve({ id: 'test-user-123', email: 'test@example.com', name: '测试用户', })), isSignedIn: jest.fn(() => Promise.resolve(true)) }; export default GoogleSignin;
3. AWS用户数据拉取Mock实现
按你实际封装的AWS请求工具结构写mock,固定返回测试用的用户详情:
// e2e/mocks/src/utils/aws-request.js export const fetchUserDetail = jest.fn(() => Promise.resolve({ userId: 'test-user-123', gender: 'female', age: 28, address: '北京市朝阳区' })); export const updateUserDetail = jest.fn(() => Promise.resolve({ success: true }));
4. Picker等组件元素定位方案
Detox基于真实原生环境运行,不存在Testing Library中无法识别原生组件的问题,按如下规则操作即可:
- 给Picker组件和每个Picker.Item添加
testID属性:
<Picker selectedValue={gender} onValueChange={(value) => setGender(value)} testID="gender-picker" > <Picker.Item label="男" value="male" testID="gender-male-option" /> <Picker.Item label="女" value="female" testID="gender-female-option" /> </Picker> {/* 选中值展示Text加testID用于验证 */} <Text testID="selected-gender-text">当前选择:{gender === 'male' ? '男' : '女'}</Text>
- Detox用例中操作和验证方式:
// 打开Picker await element(by.id('gender-picker')).tap(); // 选择对应选项 await element(by.id('gender-male-option')).tap(); // 验证选中值是否正确 await expect(element(by.id('selected-gender-text'))).toHaveText('当前选择:男');
5. 完整测试用例示例
// e2e/user-profile.spec.js describe('用户个人页测试', () => { beforeAll(async () => { await device.launchApp(); // 屏蔽真实第三方请求 await device.setURLBlacklist(['.*googleapis.com.*', '.*amazonaws.com.*']); }); beforeEach(async () => { await device.reloadReactNative(); }); it('页面加载后正确展示AWS拉取的用户信息', async () => { // 进入个人页 await element(by.id('bottom-tab-profile')).tap(); // 验证用户信息展示正确 await expect(element(by.id('user-name-text'))).toHaveText('测试用户'); await expect(element(by.id('selected-gender-text'))).toHaveText('当前选择:女'); }); it('修改Picker选项后提交更新成功', async () => { await element(by.id('bottom-tab-profile')).tap(); await element(by.id('gender-picker')).tap(); await element(by.id('gender-male-option')).tap(); await element(by.id('save-profile-btn')).tap(); await expect(element(by.id('update-success-toast'))).toBeVisible(); }); });
现有配置优化建议
你的Detox配置中testMatch字段的<roots>改为<rootDir>/e2e,避免和 Jest 单元测试用例冲突:
"testMatch": [ "<rootDir>/e2e/**/*.spec.js" ]
内容的提问来源于stack exchange,提问作者Rama Biswas
相关产品推荐
相关产品推荐

