Test method called in mounted hook Vue class component typescript

Viewed 3225

I am trying to test that a method is called on mount of Vue component. Fairly new to Vue and Typescript.

export default class App extends Vue {
    mounted () {
        this.deviceId()
        this.ipAddress()
        this.channel()
        this.show()
        this.campaign()
        this.adUnit()
    }

this approach works but I get a warning:

    it('mounted methods are called', async () => {
        
        const deviceId = jest.fn()
        wrapper = shallowMount(App, {
            methods: {
                deviceId
            }
        })
        expect(deviceId).toHaveBeenCalled()
    })

The error:

 console.error node_modules/@vue/test-utils/dist/vue-test-utils.js:1735
      [vue-test-utils]: overwriting methods via the `methods` property is deprecated and will be removed in the next major version. There is no clear migration path for the `methods` property - Vue does not support arbitrarily replacement of methods, nor should VTU. To stub a complex method extract it from the component and test it in isolation. Otherwise, the suggestion is to rethink those tests.

I have tried using jest spyOn, but I cannot find a way to access the method;

const spy = jest.spyOn(App.prototype, 'methodName')
wrapper = shallowMount(App)
expect(spy).toHaveBeenCalled()

Gives the following error:

 Cannot spy the deviceId property because it is not a function; undefined given instead

The following also doesn't work:

const spy = jest.spyOn(App.methods, 'methodName')

Error:

Property 'methods' does not exist on type 'VueConstructor<Vue>'.ts(2339)

And the following:

        const spy = jest.spyOn(App.prototype.methods, 'deviceId') 

Error:

Cannot spyOn on a primitive value; undefined given

I have read in places I may need to define an interface for the component but I am not sure how this works with defining functions inside or if it is necessary?

2 Answers

I've been facing the same issue for a few days, but I've found the way of pointing to the correct method when calling jest.spyOn().

It's a bit tricky but you'll find the methods of your class like this:

const spy = jest.spyOn(App.prototype.constructor.options.methods, 'deviceId');

Note that (even if it might seem obvious, just in case) you'll need to do this before wrapping your component, i.e. like this:

const spy = jest.spyOn(App.prototype.constructor.options.methods, 'deviceId');
wrapper = mount(App, { /* Your options go here */ });

By the way, you don't need to define methods property inside options.

Define your method under the property methods. Only then you can access them from the class.

export default class App extends Vue {
    methods: {
        deviceId(){
            console.log("do your stuff")
        }
    }
}

See here for more examples for the usage of methods

Related