最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin8浏览0评论

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?

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?

Share Improve this question asked Sep 6, 2018 at 20:21 Michael VezzaniMichael Vezzani 931 gold badge1 silver badge5 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 22

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();

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论