Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spying on a method does not work #1641

Closed
jf-niji opened this issue Aug 11, 2020 · 15 comments
Closed

Spying on a method does not work #1641

jf-niji opened this issue Aug 11, 2020 · 15 comments

Comments

@jf-niji
Copy link

jf-niji commented Aug 11, 2020

Subject of the issue

When I trigger a click event on a component when spying a function, the function is called, but the spy does not work

Steps to reproduce

Here is my component:

<template>
	<button class="close-btn no-select" @click="close" @keydown.esc="close" />
</template>

<script>
	export default {
		name: 'CoreCloseButton',

		methods: {
			close() {
				this.$emit('close')
			},
		},
	}
</script>

Here is my test:

import { shallowMount } from "@vue/test-utils"

import CoreCloseButton from "./CoreCloseButton"

describe("CoreCloseButton.vue", () => {
	it('Should call close method when click on button', async () => {
		const wrapper = shallowMount(CoreCloseButton)

                let spyClose = jest.spyOn(wrapper.vm, 'close')

                await wrapper.trigger('click')

                expect(spyClose).toBeCalled()
	})
})

Expected behaviour

The spy should be called

Actual behaviour

The spy is not called

@afontcu
Copy link
Member

afontcu commented Aug 11, 2020

Hi! You might want to spy on the component definition, not on the vm instance:

  it('Should call close method when click on button', async () => {
    const spyClose = jest.spyOn(CoreCloseButton.methods, 'close') // Notice how this line changed

    const wrapper = shallowMount(CoreCloseButton)

    await wrapper.trigger('click')

    expect(spyClose).toBeCalled()
  })

Moreover, I'd suggest not testing the internals of the component (in this case, if a specific method is called), but rather the "effects" of calling that method – the emitted event:

  it('Should call close method when click on button', async () => {
    const wrapper = shallowMount(CoreCloseButton)

    await wrapper.trigger('click')

    expect(wrapper.emitted('close')).toHaveLength(1)
  })

hope it helps!

@afontcu afontcu changed the title The click on the component does not work Spying on a method does not work Aug 11, 2020
@jf-niji
Copy link
Author

jf-niji commented Aug 11, 2020

I changed the test with your second suggestion.

With the first one, the test is unfortunately still unsuccessful...

@afontcu
Copy link
Member

afontcu commented Aug 11, 2020

Just tested it out locally and it is passing – can you share a snippet?

@jf-niji
Copy link
Author

jf-niji commented Aug 11, 2020

Oh, I did not notice that you are spying before mounting the component. It works now.

Can you explain why it is necessary to spy before mounting the component?

@jf-niji
Copy link
Author

jf-niji commented Aug 11, 2020

Here is the same test, but with 'keydown' event. And it works... :

it('Should call close method when escape key is down', async () => {
	const wrapper = shallowMount(CoreCloseButton)

	let spyClose = jest.spyOn(wrapper.vm, 'close')

	await wrapper.trigger('keydown.esc')

	expect(spyClose).toBeCalled()
})

@lmiller1990
Copy link
Member

I am also somewhat unsure why you need to spy on the method before mounting the component. 🤔

Anyway. looks like we have a solution 👍

@jf-niji
Copy link
Author

jf-niji commented Aug 17, 2020

I don't want to spy before mounting. I want to spy a method that is called by triggering a 'click' event. Please look at my test. I spy after calling shallowMount().

Yes we have a solution. But it's still weird that by triggering keydown, it works, and not with the click...

@lmiller1990
Copy link
Member

lmiller1990 commented Aug 17, 2020

Didn't you say this was working?

it('Should call close method when escape key is down', async () => {
	const wrapper = shallowMount(CoreCloseButton)

	let spyClose = jest.spyOn(wrapper.vm, 'close')

	await wrapper.trigger('keydown.esc')

	expect(spyClose).toBeCalled()
})

Did I misunderstand?

I would definitely recommend the above solution, testing the "effect" rather than trying to use spies, though.

@okakyo
Copy link

okakyo commented Nov 9, 2021

You may solve this problem if you spy on a method like this :

  it('Should call close method when click on button', async () => {
    const spyClose = jest.spyOn(CoreCloseButton.options.methods, 'close') // Notice how this line changed
    const wrapper = shallowMount(CoreCloseButton)
    await wrapper.trigger('click')
    expect(spyClose).toBeCalled()
  })

@KillianLeroux
Copy link

Your solution works for me @okakyo thank you!

@lmiller1990
Copy link
Member

Cool, FYI this won't work in VTU v2 and Vue 3 yet, but soon, follow this PR for progress vuejs/core#4216

@andercard
Copy link

This option worked for me issues#775 and I don't have to declare before the shallowMount

@beepART
Copy link

beepART commented Jan 31, 2022

I had the same issue, where I tried to use .toHaveBeenCalled(), which returned in 0 calls for me. I found out, that when I call the method with parenthesis in the component itself, my spy actually works.

from @click="addEntry" to @click="addEntry()"

@paddotk
Copy link

paddotk commented Mar 28, 2022

Strange thing, but what @beepART said works for me too. Thanks!

@Nirav-Gaglani
Copy link

@beepART Thank you for informing, I was facing the same issue. Worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants