Mocking vue-router's useRoute() in Jest tests in Vue 3

Viewed 2749

I'm using Vue 3 and Vue-Router for my app, and I'm having trouble when creating unit tests with Jest on components that use useRoute(), such as the following:

<template>
    <div :class="{ 'grey-background': !isHomeView }" />
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue';
import { useRoute } from 'vue-router';

export default defineComponent({
    setup: () => {
        const isHomeView = computed(() => {
            return useRoute().name === 'Home';
        });

        return {
            isHomeView,
        };
    },
});
</script>

The computed property is using useRoute(), and it is used in the template. When I make a Jest test on this component, an error is thrown saying TypeError: Cannot read property 'name' of undefined.

I tried mocking useRoute like so : jest.mock('vue-router', () => ({ useRoute: jest.fn() })); and then on the beforeEach: useRoute.mockReturnValueOnce({ name: 'Home' });, but it doesn't work.

I'm not talking about Vue 2 in which the router works differently but Vue 3.

1 Answers

The problem is your factory function (i.e., in { useRoute: jest.fn() }) has no mock return specified (i.e., it returns undefined), so useRoute().name is trying to access name from undefined, which generates the error you mentioned.

You could either update the mock factory to return an object with a name property:

jest.mock('vue-router', () => ({
  useRoute: jest.fn(() => ({ name: 'Home' }))
}))

...or mock them inside the tests instead of using the factory:

jest.mock('vue-router')

describe('MyFoo.vue', () => {

  it('should have grey background for Home view', () => {
    require('vue-router').useRoute.mockReturnValueOnce({ name: 'Home' })
    const wrapper = shallowMount(MyFoo)
    expect(wrapper.html()).not.toContain('grey-background')
  })

  it('should not have grey background for non-Home view', () => {
    require('vue-router').useRoute.mockReturnValueOnce({ name: 'About' })
    const wrapper = shallowMount(MyFoo)
    expect(wrapper.html()).toContain('grey-background')
  })
})

Related