mjackson / expect

Write better assertions
MIT License
2.29k stars 117 forks source link

spy was not called in react #224

Closed toearth closed 7 years ago

toearth commented 7 years ago

I got this error:

Error: spy was not called

      at assert (node_modules/expect/lib/assert.js:29:9)
      at Expectation.toHaveBeenCalled (node_modules/expect/lib/Expectation.js:318:28)
      at Object.<anonymous> (app/components/__tests__/telephone.test.js:33:31)
      at tryCallTwo (node_modules/promise/lib/core.js:45:1)
      at doResolve (node_modules/promise/lib/core.js:200:9)
      at new Promise (node_modules/promise/lib/core.js:66:1)
      at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)

My test:

import React from 'react'
import 'react-native'
import Telephone from '../telephone'
import {shallow} from 'enzyme'
import expectPackage from 'expect'

describe('Testing telephone', () => {
    it('onPress is called after press button', () => {
        const wrapper = shallow(
            <Telephone children="18623456125" />
        )
        const onPress = expectPackage.spyOn(wrapper.instance(),'onPress')
        wrapper.update()
        expectPackage(onPress).toNotHaveBeenCalled()
        wrapper.simulate('press')
        expectPackage(onPress).toHaveBeenCalled()
    })
})

Teltphone component:

export default class Telephone extends Component {

     constructor(props) {
       super(props);
       this.state = {};
     }

     onPress = () => {
         console.log('this is a test')
     }

     render() {
         let {children} = this.props
         return (
             <TouchableOpacity  onPress={this.onPress}>
                 <Text >{children}</Text>
                 <Icon name="call" color={color} size={25}  />
             </TouchableOpacity>
         )
     }
 }

It should work, doesn't it ?

ljharb commented 7 years ago

(btw i fixed your code highlighting; single backticks are for one-liners, triple backticks are for blocks)

ljharb commented 7 years ago

No, your code won't work, because onPress is already passed as a prop before you spy on it.

You have to do two things: 1) spyOn(Telephone.prototype, 'onPress') BEFORE you shallow-render it, and 2) never use class properties for functions, and instead make it a normal prototype method, but do this.onPress = this.onPress.bind(this); in the constructor.

toearth commented 7 years ago

Thanks a lot