4

I'm trying to mount a component that uses Vuex and requires $route.query to be mocked

import { mount, shallow, createLocalVue } from 'vue-test-utils'
import Vue from 'vue'
import expect from 'expect'
import Vuex from 'vuex'
import VueRouter from 'vue-router'

import Post from '../../components/Post.vue'

const localVue = createLocalVue()

localVue.use(Vuex);
localVue.use(VueRouter);

describe('Lead list', () => {
    let wrapper;
    let getters;
    let store;

    beforeEach(() => {

        getters = {
            post: () => { return {} }
        }
        store = new Vuex.Store({
            getters
        });

    });


    it('should just be true', () => {

        const $route = {
            path: '/some/path',
            query: {}
        }

        wrapper = shallow(Post, {
            localVue,
            mocks: {
                $route
            }, store
        });

        expect(true).toBe(true);

    });
});

And I'm getting back this error

TypeError: Cannot set property $route of #<VueComponent> which has only a getter

I've found the closed issue https://github.com/vuejs/vue-test-utils/issues/142 that has similar error. But my case is a little different. If I remove store or mocks from the options it works fine, but it does't work when you have both. Is this an issue or I'm doing something wrong?

Thanks

1 Answer 1

9

You're getting this error because you have installed VueRouter on the Vue constructor, by calling localVue.use(VueRouter). This adds $route as a read only property on the localVue constructor.

You're then trying to overwrite $router using mocks. mocks is unable to overwrite $route because it's been added as a read only property by Vue Router.

To fix your problem, you could create another localVue, install Vuex, and then use mocks to pass in $route:

it('should just be true', () => {
  const freshLocalVue = createLocalVue()
  freshLocalVue.use(Vuex)
  const $route = {
    path: '/some/path',
    query: {}
  }

  wrapper = shallow(Post, {
      localVue,
      mocks: {
          $route
      }, 
      store
  })

  expect(true).toBe(true)
})
Sign up to request clarification or add additional context in comments.

4 Comments

I managed to make it work by using freshLocalVue.use(VueRouter) instead of Vuex. But you definitely pointed me in the right direction. Thanks!
I can't get this to work. Either there's a router, and $route can't be mocked, or there's no router and I get tons of errors because the code depends on a router. I don't understand the design decision that $route can't be mocked.
this works but without freshLocalVue.use(VueRouter) I get warnings about unknown custom element <router-link>. Anybody know how to fix this?
@r_zelazny regarding the unknown router-link, see the vue-test-utils docs. You can basically stub them by adding stubs: ['router-link', 'router-view'] to your shallowMount/mount properties.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.