简体   繁体   中英

Using Jest, how do I spyon an extended component's method when unit testing a single file component in vue.js

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 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?

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')

ComponentA is a component definition with update as a child of the methods attribute so update will not be found on ComponentA or ComponentB . spyOn should be applied on the instance of the component instead.

const wrapper = shallowMount(ComponentB, { propsData: { ... } });

// create a spy on the instance method
const spyUpdate = jest.spyOn(wrapper.vm, 'update')

// replace the instance method with the spy
wrapper.setMethods({ update: spyUpdate });

// your tests ...

// verify the spy was called
expect(spyUpdate).toHaveBeenCalled();

// remove the spy
spyUpdate.mockReset();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM