为 vuex 开玩笑,测试同一动作的不同返回值

Posted

技术标签:

【中文标题】为 vuex 开玩笑,测试同一动作的不同返回值【英文标题】:Jest for vuex, test different return values for a same action 【发布时间】:2021-02-11 00:46:19 【问题描述】:

对于看起来像这样的组件:(简化)

@Component
export default class MyComp extends Vue 

  private status = 'error';

  async create() 
    const result = await this.$store.dispatch('create', payload);
    if (result.code) 
      this.status = 'error';
     else 
      this.status = 'success';
    
  

在规范中,我尝试使用

模拟创建操作
    actions = 
        create: () => jest.fn()
            .mockReturnValueOnce( code: true, message: 'error' ) // mock an error on first call
            .mockReturnValueOnce( code: false ) // mock success on second call
    

然后我调用 create 两次

    wrapper.vm.create();
    console.log(wrapper.vm.$data.status);
    wrapper.vm.create();
    console.log(wrapper.vm.$data.status);

this.status 不会改变。

接下来我尝试的是单动作模拟

create: () => ( code: true, message: 'error' )

然后在测试过程中改变动作

    wrapper.vm.create();
    console.log(wrapper.vm.$data.status);
    actions.create = () => ( code: false );
    store.hotUpdate( actions );
    wrapper.vm.create();
    console.log(wrapper.vm.$data.status);

不过,状态不会改变。

如何测试这个简单的 if/else 逻辑?

编辑:

在 if 和 else 分支中添加控制台日志我可以看到测试中的模拟操作确实有效(覆盖率为 100%)并返回正确的数据。所以每次都会执行this.status=xx

但它看起来不像 this.status 链接到 wrapper.vm.$data.status

我尝试了 nexttick() 和 forceUpdate() 的所有方式,仍然没有运气。 修改 this.status 时,wrapper.vm.$data.status 不会改变。

【问题讨论】:

【参考方案1】:

经过大量试验和错误后,我发现 nexttick 和 forceupdate 的正确组合可以使代码正常工作。

    actions.create = () => Promise.resolve( code: false );
    store.hotUpdate( actions );
    await wrapper.vm.$forceUpdate();
    wrapper.vm.create();
    await wrapper.vm.$nextTick();
    await wrapper.vm.$forceUpdate();
    expect(wrapper.vm.$data.status).toEqual('success');

如果我删除 nexttick 或其中任何一个 forceupdate,测试不会通过。

【讨论】:

以上是关于为 vuex 开玩笑,测试同一动作的不同返回值的主要内容,如果未能解决你的问题,请参考以下文章

返回 jQuery 承诺的 Vuex 动作不起作用,.fail 不是函数

在开玩笑的模拟模块工厂中模拟一个承诺

我们可以修改 Vuex 操作以进行开玩笑的单元测试吗?

测试一个 redux 动作

开玩笑单元测试返回“MongoError:拓扑被破坏”

玩笑,用酶测试同一子组件的多次出现