如何在Alert中模拟'onPress'事件?

21

我可以模拟弹出警报来测试其alert方法是否被调用,但我真正想要测试的是按下警报中的确定按钮。

import { Alert } from 'react-native';

it('Mocking Alert', () => {
    jest.mock('Alert', () => {
        return {
          alert: jest.fn()
          }
        };
      });

    const spy = jest.spyOn(Alert, 'alert');
    const wrapper = shallow(<Search />);

    wrapper.findWhere(n => n.props().title == 'Submit').simulate('Press');
    expect(spy).toHaveBeenCalled(); //passes
})

我绝对不确定如何进行测试。这是一个通用组件,我想要测试它。


export default class Search extends Component{

    state = {
      someState: false
    }

    confirmSubmit(){
      this.setState(state => ({someState: !state.someState}))
    }

    onPress = () => {
      Alert.alert(
        'Confirm',
        'Are you sure?'
        [{text: 'Ok', onPress: this.confirmSubmit}] //<-- want to test this
      )
    }

    render(){
      return(
       <View>
         <Button title='Submit' onPress={this.onPress}
       </View>
      )
    }
}

有人尝试过这个吗?

3个回答

24
我会嘲讽该模块并将其导入以在间谍上进行测试。然后触发点击事件。这将调用 spy。通过使用 mock.calls 来获取 onPress 方法并调用它,您可以获得其被调用时的参数。然后您就可以测试组件的状态了。
import Alert from 'Alert'

jest.mock('Alert', () => {
    return {
      alert: jest.fn()
    }
});


it('Mocking Alert', () => {
    const wrapper = shallow(<Search />);
    wrapper.findWhere(n => n.props().title == 'Submit').simulate('Press');
    expect(Alert.alert).toHaveBeenCalled(); // passes
    Alert.alert.mock.calls[0][2][0].onPress() // trigger the function within the array
    expect(wrapper.state('someState')).toBe(true)
})

1
抱歉,我应该在我的问题中包含那个。这基本上就是我已经在做的事情了。我已经在测试中导入了Alert。我想要测试的是警报方法内的onPress。Alert.alert( '确认', '你确定吗?' [{text: '好的', onPress: this.confirmSubmit}] //<-- 想要测试这个 ) - Anthony Urbina
1
已更新答案以反映您实际的问题。 - Andreas Köberle
2
它对我不起作用 `expect(jest.fn())[.not].toHaveBeenCalled()jest.fn()的值必须是模拟函数或间谍。` - marco
2
从第一次模拟调用(mock.calls[0])获取第三个参数([2]), 这是数组[{text: 'Ok', onPress: this.confirmSubmit}], 所以从中获取第一项([0])。 - Andreas Köberle
1
如果 Alert.alert.mock.calls[0][2][0].onPress() 出现编译时错误,例如 Property 'mock' does not exist on type '(title: string, message?: string, buttons?: AlertButton[], options?: AlertOptions, type?: string) => void'.,那么请使用 Alert.alert['mock'].calls[0][2][0].onPress() 的表示法。 - Nar Gar
显示剩余6条评论

11

我在测试Alert并尝试模拟Alert的onPress时遇到了同样的问题。我正在使用TypeScript实现我的代码。我通过使用spyOn来处理这个问题:

const spyAlert = jest.spyOn(Alert, 'alert');

然后要使用 onPress,您需要忽略该行的类型检查,否则您将收到“无法调用可能是'undefined'的对象”的错误。

// @ts-ignore
spyAlert.mock.calls[0][2][0].onPress();

谢谢。帮我省了很多功夫去弄清楚这个! - undefined

0
这是一个模拟实现警报的示例,它会自动调用最后一个按钮的回调函数:
jest.spyOn(Alert, 'alert').mockImplementation((title, message, buttons) => {
  if (!buttons) return
  const lastButton = buttons[buttons.length - 1]
  lastButton.onPress && lastButton.onPress()
})

你可以将它添加到一个`jest.setup.ts`文件中,使得每个测试都能使用,或者在需要使用的测试中手动添加。
无论哪种方式,你都可以检查它是否被调用: expect(Alert.alert).toHaveBeenCalled() 并且确认它已经被正确地调用:
expect(Alert.alert).toHaveBeenCalledWith(
  'Confirm',
  'Are you sure?',
   expect.any(Array),
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接