You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:15:05