Find the Vue.js 3 version .

You can find the test described on this page here.

Why stub?

When writing unit tests, often we want to stub parts of the code we are not interested in. A stub is simply a piece of code that stands in for another. Let’s say you are writing a test for a <UserContainer> component. It looks like this:

<UsersDisplay> has a created lifecycle method like this:

  1. created() {
  2. axios.get("/users")
  3. }

We want to write a test that asserts <UsersDisplay> is rendered.

One way to prevent the <UsersDisplay> from initiating the ajax request is by stubbing the component out. Let’s write our own components and test, to get a better understanding of the different ways and benefits of using stubs.

This example will use two components. The first is ParentWithAPICallChild, which simply renders another component:

  1. <template>
  2. <ComponentWithAsyncCall />
  3. </template>
  4. <script>
  5. import ComponentWithAsyncCall from "./ComponentWithAsyncCall.vue"
  6. name: "ParentWithAPICallChild",
  7. components: {
  8. ComponentWithAsyncCall
  9. }
  10. </script>

<ParentWithAPICallChild> is a simple component. It’s sole responsibility is to render <ComponentWithAsyncCall>. <ComponentWithAsyncCall>, as the name suggests, makes an ajax call using the axios http client:

<ComponentWithAsyncCall> calls makeApiCall in the created lifecycle hook.

Write a test using mount

Let’s start off by writing a test to verify that <ComponentWithAsyncCall> is rendered:

  1. import { shallowMount, mount } from '@vue/test-utils'
  2. import ParentWithAPICallChild from '@/components/ParentWithAPICallChild.vue'
  3. import ComponentWithAsyncCall from '@/components/ComponentWithAsyncCall.vue'
  4. describe('ParentWithAPICallChild.vue', () => {
  5. it('renders with mount and does initialize API call', () => {
  6. const wrapper = mount(ParentWithAPICallChild)
  7. expect(wrapper.find(ComponentWithAsyncCall).exists()).toBe(true)
  8. })
  1. PASS tests/unit/ParentWithAPICallChild.spec.js
  2. console.log src/components/ComponentWithAsyncCall.vue:17
  3. Making api call

The test is passing - great! However, we can do better. Notice the console.log in the test output - this comes from the makeApiCall method. Ideally we don’t want to make calls to external services in our unit tests, especially when it’s from a component that is not the main focus of the current test. We can use the stubs mounting option, described in the vue-test-utils docs .

Let’s update the test, this time stubbing :

The test still passes when yarn test:unit is run, however the console.log is nowhere to be seen. That’s because passing [component]: true to stubs replaced the original component with a stub. The external interface is still the same (we can still select it using find, since the name property, which is used internally by find, is still the same). The internal methods, such as makeApiCall, are replaced by dummy methods that don’t do anything - they are “stubbed out”.

You can also specify the markup to use for the stub, if you like:

  1. const wrapper = mount(ParentWithAPICallChild, {
  2. stubs: {
  3. ComponentWithAsyncCall: "<div class='stub'></div>"
  4. }
  5. })

Automatically stubbing with shallowMount

Instead of using mount and manually stubbing <ComponentWithAsyncCall>, we can simply use shallowMount, which automatically stubs any other components by default. The test with shallowMount looks like this:

  1. it('renders with shallowMount and does not initialize API call', () => {
  2. const wrapper = shallowMount(ParentWithAPICallChild)
  3. expect(wrapper.find(ComponentWithAsyncCall).exists()).toBe(true)
  4. })
  • stubs is useful for stubbing out the behavior of children that is unrelated to the current unit test
  • you can pass true to create a default stub, or pass your own custom implementation

You can find the test described on this page here.