This book is written for Vue.js 3 and Vue Test Utils v2.

Find the Vue.js 2 version here.

Two ways to render

vue-test-utils provides two ways to render, or mount a component - mount and shallowMount. A component mounted using either of these methods returns a wrapper, which is an object containing the Vue component, plus some useful methods for testing.

Let’s start off with two simple components:

  1. const Child = Vue.component("Child", {
  2. name: "Child",
  3. template: "<div>Child component</div>"
  4. })
  5. const Parent = Vue.component("Parent", {
  6. name: "Parent",
  7. template: "<div><child /></div>"
  8. })

Let’s start off by rendering Child and calling the html method vue-test-utils provides to inspect the markup.

  1. const shallowWrapper = shallowMount(Child)
  2. const mountWrapper = mount(Child)
  3. console.log(shallowWrapper.html())
  4. console.log(mountWrapper.html())

Both mountWrapper.html() and shallowWrapper.html() yield the following output:

  1. <div>Child component</div>

No difference here. How about with Parent?

  1. const shallowWrapper = shallowMount(Parent)
  2. const mountWrapper = mount(Parent)
  3. console.log(shallowWrapper.html())
  4. console.log(mountWrapper.html())

mountWrapper.html() now yields:

  1. <div><div>Child component</div></div>

Which is the completely rendered markup of Parent and Child. shallowWrapper.html(), on the other hand, produces this:

  1. <div><vuecomponent-stub></vuecomponent-stub></div>

The place where <Child /> should be has been replaced by <vuecomponent-stub />. shallowMount renders regular html elements, but replaces Vue components with a stub.

A stub is kind of a “fake” object that stands in for a real one.

This can be useful. Imagine you want to test your App.vue component, that looks like this:

  1. <template>
  2. <div>
  3. <h1>My Vue App</h1>
  4. <fetch-data />
  5. </div>
  6. </template>

And we want to test <h1>My Vue App</h1> is rendered correctly. We also have a <fetch-data> component, that makes a request to an external API in its mounted lifecycle hook.

If we use mount, although all we want to do is assert some text is rendered, <fetch-data /> will make an API request. This will make our test slow and prone to failure. So, we stub out external dependencies. By using shallowMount, <fetch-data /> will be replaced with a <vuecomponent-stub />, and the API call will not be initiated.

As a rule of thumb, you should try to use mount, since that will more closely resemble your components and how they will appear in a real environment. That said, if you are having trouble with many API requests firing, or supplying the necessary dependencies to render your component, you can use shallowMount.: