I'm currently trying to get a single file component (ComponentB
) unit tested using Jest and vue-test-utils. ComponentB
extends ComponentA
, which has a method update(product)
defined in it.
/* -------- Component B -------- */
<script>
import ComponentA from './ComponentA'
export default {
extends: ComponentA,
props: [...],
data: () => {
productData: {foo: 'bar', baz: 'shiz'}
},
methods: {
updateProduct() {
this.update(this.productData)
}
}
}
</script>
/* -------- Component A -------- */
<script>
export default {
props: [...],
data: () => {...},
methods: {
update(productData) {
...
}
}
}
</script>
I then attempt a unit test in which I shallowMount()
my ComponentB
and try to jest.spyOn
that update(productData)
method that is defined in ComponentA
. The test looks like this:
it('calls update with data when input is added to the field', () => {
const spy = jest.spyOn(ComponentA, 'update);
const wrapper = shallowMount(ComponentB, { propsData: { ... } });
const contractIdInput = wrapper.find('#contract-id-input > b-form-input');
contractIdInput.element.value = 'foobar';
contractIdInput.trigger('input')
expect(spy).toHaveBeenCalledWith(...someDataHere...)
});
When I run this test, I get a Cannot spy the update property because it is not a function; undefined given instead
.
I'm not entirely sure why this isn't working, though I do have some ideas.
First, because I am shallowMount()
ing my ComponentB
, it isn't going to know anything about its parent component, and thus not have access to the update(productData)
method that is defined on ComponentA
.
Second, perhaps I'm not calling jest.spyOn()
at the right time, and should instead call it after I create the wrapper object of ComponentB
. However, I tried changing this around and didn't have any success or different behavior.
So my question is, how do I spy on a method that is provided by an extended component when I am shallow mounting the component under test?
To test method implementation using spies with Jest we use the jest. spyOn() function. jest. spyOn() is called with two required parameters - the object and the object method identifier we're spying on.
If you are using the Vue CLI to build your project, you can use the plugin cli-plugin-unit-jest to run Jest tests. The plugin pulls all required dependencies (including jest), creates a jest.
createLocalVue returns a Vue class for you to add components, mixins and install plugins without polluting the global Vue class. The errorHandler option can be used to handle uncaught errors during component render function and watchers.
Just to add to the answer above of @user2718281, SetMethods
it's deprecated, so you better define the spyOn pointing to the ComponentB before instantiating like this:
// create a spy before the instance is created
const spySomeMethod = jest.spyOn(ComponentB.methods, 'someMethod')
const spyUpdate = jest.spyOn(ComponentB.methods, 'update')
const wrapper = shallowMount(ComponentB, { propsData: { ... } });
// your tests ...
// verify the spy was called
expect(spyUpdate).toHaveBeenCalled();
// remove the spy
spyUpdate.mockReset();
And about the question maybe you are forgetting to add the ComponentA.methods
like this:
const spySomeMethod = jest.spyOn(ComponentB.methods, 'someMethod')
but if you want to test some lifecycle method event like mounted
or created
remove the .methods
like this:
const spySomeMethod = jest.spyOn(ComponentB, 'created')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With