vue jest spyOn 在计算观察者方法调用时不起作用

Posted

技术标签:

【中文标题】vue jest spyOn 在计算观察者方法调用时不起作用【英文标题】:vue jest spyOn not working when calculating watcher method calls 【发布时间】:2020-06-27 22:58:39 【问题描述】:

我正在熟悉 jest 和 vue,我想了解如何确保在 prop 更改时触发方法。在这种特殊情况下,这是微不足道的,这似乎是直截了当的。但它不起作用。

组件观察器

@Watch("id")
    public async idChanged() 
        this.calculateStatus();
    

beforeEach - 这会为每个测试初始化​​包装器

beforeEach(async () => 
        var httpClient = new PemHttpClient(vue);
        var v3ReferenceDatumService = new V3ReferenceDatumService(httpClient, "");
        var contractService = new V3ContractService(httpClient, "", v3ReferenceDatumService);

        wrapper = mount(AmendmentIdDisplay, 
            provide: 
                v3ContractService: contractService,
            ,
            propsData: 
                id: "82.5.1"
            
        );

        await wrapper.vm.$nextTick();
    )

笑话测试

        let calculateFired = jest.spyOn(wrapper.vm, "calculateStatus");

        wrapper.setProps(
            ...wrapper.props(),
            id: "1"
        )

        await wrapper.vm.$nextTick();

        expect(calculateFired).toBeCalled();

我希望间谍增加了呼叫计数器,但事实并非如此。它保持为零。如果我手动调用 wrapper.vm.calculateStatus(),间谍可以正常工作。所以 setProps 要么根本没有触发观察者,要么发生了一些奇怪的引用事情,导致在观察者中调用的方法不是我正在监视的方法。我不确定是哪个。

【问题讨论】:

【参考方案1】:

我希望现在还为时不晚。是的,jest.spyOn() 和 vue 观察者存在问题。我有一个技巧可以暂时解决问题(仅在同步功能上测试):

const insertSpyWatcher = (vueInstance: any, watcherExpression: string, spyInstance: jest.SpyInstance) => 
  let oldWatcherIndex = -1;
  let deep = false; // pass the deep option value from the original watcher to the spyInstance

  // find the corresponding watcher
  vueInstance._watchers.forEach((watcher: any, index: number) => 
    if (watcher.expression === watcherExpression) 
      oldWatcherIndex = index;
      deep = watcher.deep;
    
  );

  // remove the existing watcher
  if (oldWatcherIndex >= 0) 
    vueInstance._watchers.splice(oldWatcherIndex, 1);
   else 
    throw new Error(`No watchers found with name $watcherExpression`);
  

  // replace it with our watcher
  const unwatch = vueInstance.$watch(watcherExpression, spyInstance,  deep );
  return unwatch;
;

然后在你的测试中:

it('test the watcher call', () => 
  let calculateFired = jest.spyOn(wrapper.vm, "calculateStatus");
  insertSpyWatcher(wrapper.vm, "id", calculateFired) // Yes 'id' is the name of the watched property
  wrapper.setProps(
    ...wrapper.props(),
    id: "1"
  )
  await wrapper.vm.$nextTick();
  expect(calculateFired).toBeCalled();
);

如果需要immmediate 属性,您可以随时将其添加为insertSpyWatcher 的参数。我没有找到获取原始观察者的immediateproperty 的方法。

【讨论】:

感谢您的回复。我还不能对此进行测试,因为我们已经恢复了一些“必须在季度末完成”的工作。因此,我会在此添加书签,并在我回到实施我们的笑话设置时试一试。 @Lyokolux 你对你提到的 jest.spyOn 和 vue watchers 的问题有参考吗?我想关注它的任何更新。

以上是关于vue jest spyOn 在计算观察者方法调用时不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Vue 检查动作是不是使用 spyOn 调用其他动作

jest中的mock,jest.fn()jest.spyOn()jest.mock()

jest中的mock,jest.fn()jest.spyOn()jest.mock()

jest中的mock,jest.fn()jest.spyOn()jest.mock()

javascript VUE Jest spyOn

Vue & Jest。子组件发出事件时调用测试方法