VUE

shallowMount vs mount in vue test utils with an example

In this post, we will see the differences between shallowMount and mount functions in vue-test-utils library and what they both offer us in terms of unit testing in Vue applications.

If you want to know how to set up unit tests for the Vue project, check my article on how to do it.

Let’s have an App.vue and HelloWorld.vue files and HelloWorld component is a child component of App.vue.

The App component passes msg as a prop to the HelloWorld component and the hello world component will display the passed message.

The above code diagram is our example for this blog post to understand mount and shallowMount functions.

What is a mount() function?

The mount function takes in the Vue component as a first argument and has options as a second argument. The mount function will return Vue instance wrapper of the component passed in.

So, If I mount the App component, I can have access to the child component’s DOM elements as well.

The purpose of the mount function is (per my understanding)

When changing a property or something in the parent component, If there’s a change to the DOM element in the child component, then we can assert the child element properties to see if it matches the expectation.

Mount() function in Action

Here is the App.vue component.

<template>
  <div id="app">
    <HelloWorld :msg="msg" />
  </div>
</template>
...
export default {
  name: "App",
  components: {
    HelloWorld
  },
  data() {
    return {
      msg: "Welcome to Your Vue.js App"
    };
  }
};

Now, let’s write unit tests for App.vue file.

import { mount } from "@vue/test-utils";
import App from "@/App.vue";

describe("App.vue Tests", () => {
  it("message passed from App -> Hello World should be rendered", () => {
    const msg = "Hello World";
    const wrapper = mount(App, {
      data() {
        return {
          msg: msg
        };
      }
    });
    expect(wrapper.find("div.hello > h1").text()).toBe(msg);
  });
});

We set up our mount function to have our custom message(msg) in the data() function. The msg variable is passed on to the HelloWorld component from the App component. And our text in the H1 tag should now reflect what we have in the msg variable in the test.

So, if you want to write tests that include testing a child component’s also, then you can use the mount function on the parent element to render the component with its children and assert what you want.

What is a shallowMount() function?

Unlike mount function, shallowMount function will just load the component itself ignoring the child component(s).

If you want to write unit tests for a component, then shallowMount function is the right choice.

If we replace the mount function with shallowMount in the above mounted tests for App component, the test will fail as the shallowMount cannot load the HelloWorld component and unable to locate the div.hello > h1 in the component.

Let me run the test by replacing mount >> shallowMount and see what happens.

it("message passed from App -> Hello World will not be rendered", () => {
    const msg = "Hello World";
    const wrapper = shallowMount(App, {
      data() {
        return {
          msg: msg
        };
      }
    });
    expect(wrapper.find("div.hello > h1").text()).toBe(msg);
  });

Here’s the output after running the test

  ● App.vue Tests › message passed from App -> Hello World will not be rendered

    [vue-test-utils]: find did not return div.hello > h1, cannot call text() on empty Wrapper

      12 |       }
      13 |     });
    > 14 |     expect(wrapper.find("div.hello > h1").text()).toBe(msg);
         |                                           ^
      15 |   });
      16 | });
      17 | 

      at throwError (node_modules/@vue/test-utils/dist/vue-test-utils.js:1709:9)
      at Object.<anonymous> (tests/unit/app.spec.js:14:43)

The wrapper is empty after finding the div.hello > h1. So, the test failed.

Writing unit test with shallowMount function

How to pass the above failing unit test?

Instead of testing the App.vue component, test the HelloWorld component alone by using the shallowMount function. As we are interested in checking what the HelloWorld component renders in H1 tag when a message is passed.

Before we write a test for HelloWorld component, here’s what the Hello World component looks like.

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
  ...
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  }
};
</script>

Let’s write a test for HelloWorld component.

import { shallowMount } from "@vue/test-utils";
import HelloWorld from "@/components/HelloWorld";

describe("HelloWorld.vue", () => {
  it("H1 tag should render what is passed into the props", () => {
    const msg = "Hello World again";
    const wrapper = shallowMount(HelloWorld, {
      propsData: {
        msg: msg
      }
    });
    expect(wrapper.find("h1").text()).toBe(msg);
  });
});

We will use the propsData option to pass our data to the msg prop and verify if we got what we have passed in using the expect function.

If we run, the test should pass now.

Conclusion

If you are writing unit tests and want to test the functionality of a component individually, then setup the shallowMount function and test it.

If you want to test a nested component, then use the mount function.

I’d recommend using shallowMount function, as it’s for unit testing a component. If you have a nested component, then write tests for the component.

References

Disqus Comments Loading...
Share
Published by
Karthik Chintala

Recent Posts

2 Good Tools To Test gRPC Server Applications

In this post, we’ll see how to test gRPC Server applications using different clients. And… Read More

2 years ago

Exploring gRPC project in ASP.NET Core

In this post, we'll create a new gRPC project in ASP.NET Core and see what's… Read More

2 years ago

Run dotnet core projects without opening visual studio

In this blog post, we’ll see how to run dotnet core projects without opening visual… Read More

2 years ago

Programmatically evaluating policies in ASP.NET Core

Programmatically evaluating policies is useful when we want to provide access or hide some data… Read More

2 years ago

Multiple authorization handlers for the same requirement in ASP.NET Core

We saw how we could set up policy-based authorization in our previous article. In this… Read More

2 years ago

Policy-Based Authorization in ASP.NET Core

What is policy-based authorization and how to set up policy-based authorization with handlers and policies… Read More

2 years ago

This website uses cookies.