This book is written for Vue.js 2 and Vue Test Utils v1.

Find the Vue.js 3 version here.

Mocking global objects

vue-test-utils provides a simple way to mock global objects attached to Vue.prototype, both on test by test basis and to set a default mock for all tests.

The test used in the following example can be found hereMocking global objects - 图1.

The mocks mounting option

The mocks mounting optionMocking global objects - 图2 is one way to set the value of any properties attached to Vue.prototype. This commonly includes:

  • $store, for Vuex
  • $router, for Vue Router
  • $t, for vue-i18n

and many others.

Example with vue-i18n

Use with Vuex and Vue Router are discussed in the respective sections, hereMocking global objects - 图3 and hereMocking global objects - 图4. Let’s see an example with vue-i18nMocking global objects - 图5. While it would be possible to use createLocalVue and install vue-i18n for each test, that would quickly get cumbersome and introduce a lot of boilerplate. First, a <Bilingual> component that uses vue-i18n:

  1. <template>
  2. <div class="hello">
  3. {{ $t("helloWorld") }}
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "Bilingual"
  9. }
  10. </script>

The way vue-i18n works is you declare your translation in another file, then reference them with $t. For the purpose of this test it doesn’t really matter what the translation file looks like, but for this component it could look like this:

  1. export default {
  2. "en": {
  3. helloWorld: "Hello world!"
  4. },
  5. "ja": {
  6. helloWorld: "こんにちは、世界!"
  7. }
  8. }

Based on the locale, the correct translation is rendered. Let’s try and render the component in a test, without any mocking.

  1. import { mount } from "@vue/test-utils"
  2. import Bilingual from "@/components/Bilingual.vue"
  3. describe("Bilingual", () => {
  4. it("renders successfully", () => {
  5. const wrapper = mount(Bilingual)
  6. })
  7. })

Running this test with yarn test:unit throws a huge stack trace. If you look through the output carefully, you can see:

  1. [Vue warn]: Error in config.errorHandler: "TypeError: _vm.$t is not a function"

This is because we did not install vue-i18n, so the global $t method does not exist. Let’s mock it using the mocks mounting option:

  1. import { mount } from "@vue/test-utils"
  2. import Bilingual from "@/components/Bilingual.vue"
  3. describe("Bilingual", () => {
  4. it("renders successfully", () => {
  5. const wrapper = mount(Bilingual, {
  6. mocks: {
  7. $t: (msg) => msg
  8. }
  9. })
  10. })
  11. })

Now the test passes! There are lots of uses for the mocks option. Most frequently I find myself mocking the global objects provided by the three packages mentioned above.

Settings default mocks using config

Sometimes you want to have a default value for the mock, so you don’t create it on a test by test basis. You can do this using the configMocking global objects - 图6 API provided by vue-test-utils. Let’s expand the vue-i18n example. You can set default mocks anywhere by doing the following:

  1. import { config } from "@vue/test-utils"
  2. config.mocks["mock"] = "Default Mock Value"

The demo project for this guide is using Jest, so I will declare the default mock in jest.init.js, which is loaded before the tests are run automatically. I will also import the example translations object from earlier, and use it in the mock implementation.

  1. import VueTestUtils from "@vue/test-utils"
  2. import translations from "./src/translations.js"
  3. const locale = "en"
  4. VueTestUtils.config.mocks["$t"] = (msg) => translations[locale][msg]

Now a real translation will be rendered, despite using a mocked $t function. Run the test again, this time using console.log on wrapper.html() and removing the mocks mounting option:

  1. describe("Bilingual", () => {
  2. it("renders successfully", () => {
  3. const wrapper = mount(Bilingual)
  4. console.log(wrapper.html())
  5. })
  6. })

The test passes, and the following markup is rendered:

  1. <div class="hello">
  2. Hello world!
  3. </div>

You can read about using mocks to test Vuex hereMocking global objects - 图7. The technique is the same.

Conclusion

This guide discussed:

  • using mocks to mock a global object on a test by test basis
  • using config.mocks to set a default mock