在组件导航守卫中测试 Vue Router

Testing Vue Router in component navigation guard

我正在尝试对一个组件进行单元测试(使用 vue-test-utils),该组件在组件导航防护中有一个 beforeRouteUpdate,如下所示:

    <template>
       ...
    </template>
    <script>
    export default {
        computed: {
            ...
        }
        ...
        beforeRouteUpdate(to, from, next) {
            // code to be tested
            this.$store.dispatch('setActiveTask')
        }
    }
    </script>

我确实在测试文件中使用 shallowMount 渲染组件并模拟 $store.

之类的东西
    beforeEach(() => {
        cmp = shallowMount(Task, {
                    mocks: {
                        $store: store,
                        $route: {
                            params: {
                                taskID: 12,
                                programID: 1
                            }
                        }
                    },
                    i18n: new VueI18N({
                        silentTranslationWarn: true
                    }),
                    stubs: {
                        'default-layout': EmptySlotComponent,
                        'nested-router': EmptySlotComponent,
                        RouterLink: RouterLinkStub
                    }
                })
    })

    it('has beforeRouteUpdate hook', () => {
        // how do i call beforeRouteUpdate now?
        // cmp.vm.beforeRouteUpdate(...)
    }

有人对此有什么想法吗?

更新: 我使用 @vue/cli 和 Mocha + Chai 作为单元测试工具创建了一个最小示例,可以在此处找到:https://github.com/BerniWittmann/vue-test-navigation-guard-reproduction

成功了,但使用了一种老掉牙的解决方案。 我的测试现在看起来像这样:

it('test', () => {
    const beforeRouteUpdate = wrapper.vm.$options.beforeRouteUpdate
    const $store = {
        dispatch: () => {
        }
    }
    spyOn($store, 'dispatch').and.returnValue({ then: (arg) => arg() })

    let next = jasmine.createSpy('next')
    render()

    beforeRouteUpdate.call({ $store }, {
        params: {
            taskID: 1
        }
    }, {}, next)

    expect($store.dispatch).toHaveBeenCalledWith('setActiveTask', 1)
    expect(next).toHaveBeenCalled()
})

导航守卫在 wrapper.vm.$options.beforeRouteUpdate 中可用,但是调用它我丢失了 this 的上下文,所以我无法在组件导航守卫中调用 this.$store.dispatch,这就是原因我需要使用 .call() 方法

以下代码对我测试路由导航守卫来说效果很好。

const beforeRouteUpdate = wrapper.vm.$options.beforeRouteUpdate[0];
let nextFun = jest.fn();
beforeRouteUpdate.call(wrapper.vm , "toObj", "fromObj", nextFun); 

testing route navigation guards git hub

how to test vue router beforeupdate navigation guard