Unit Testing

Share:

In this chapter, we will delve into the framework of VueJS for unit testing. Testing is an essential part of software development that helps to create a seamless user experience by catching and fixing bugs before a product's release. Learning how to conduct unit testing in VueJS will be like directing a movie scene, where each part of the production, such as the characters, storyline, and effects (the equivalent of components, state, and props in VueJS), are independently tested for optimal performance.

Unit testing is a software testing methodology where individual units of source code are tested to verify whether they behave as expected. In the VueJS theatre, this implies testing isolated Vue components without any actual interaction with other parts of the application. A unit test provides a strict, written contract that a piece of code must conform to.

We'll be making use of the Vue Test Utils library and the Jest testing framework to conduct our unit tests. Vue Test Utils is the official unit-testing utility library for Vue.js. Jest, on the other hand, is a delightful JavaScript Testing Framework with units like snapshots and promises that make testing delightful.

Before beginning, you should have Vue Test Utils and Jest installed in your application. If not, you can add them using npm or yarn:

npm install --save-dev @vue/test-utils jest

or

yarn add --dev @vue/test-utils jest

Let's begin with a simple Vue component, a MovieCard component, which just shows the title and director of a movie:

<template>
  <div>
    <h1>{{ movie.title }}</h1>
    <p>Directed by {{ movie.director }}</p>
  </div>
</template>

<script>
export default {
  props: {
    movie: Object
  }
}
</script>

To make a unit test of the MovieCard component, we create a new file called MovieCard.spec.js. Note the .spec. in the filename as it signifies that this file is a test.

Our objective is to verify that the MovieCard component correctly displays the title and director. Here's how we'd do it:

// Import Vue and the component being tested
import { shallowMount } from '@vue/test-utils'
import MovieCard from '@/components/MovieCard.vue'

// Here is our little test suite
describe('MovieCard.vue', () => {
  // Inspection of the raw component options
  it('has a created hook', () => {
    // Define some props
    const movie = {
      title: 'Inception',
      director: 'Christopher Nolan'
    }
    // Mount the component
    const wrapper = shallowMount(MovieCard, {
      propsData: { movie }
    })

    expect(wrapper.find('h1').text()).toBe(movie.title)
    expect(wrapper.find('p').text()).toBe(`Directed by ${movie.director}`)
  })
})

This example raises a few points about unit testing in Vue:

  1. We used a helper function from Vue Test Utils called shallowMount() to create a Wrapper that contains the mounted and rendered Vue component.

  2. We used Jest's describe() and it() functions to organize our tests into a "suite" and "cases", making the test organized and readable.

  3. The propsData option passed into shallowMount() allows us to create a movie prop and set it to our predefined movie object, just like in a real-life scenario.

  4. Finally, we used Jest's expect() function to assert that the text of our component's h1 and p tags is correctly rendered.

Now, imagine we had a list of movies in a MoviesList component, and we wanted to ensure that the correct number of MovieCard components is being rendered. Let's see how we can add a test for that:

<template>
  <div>
    <MovieCard
      v-for="movie in movies"
      :key="movie.id"
      :movie="movie"
    />
  </div>
</template>

<script>
import MovieCard from './MovieCard.vue'

export default {
  components: {
    MovieCard
  },
  props: {
    movies: Array
  }
}
</script>

And the test would look like:

import { shallowMount } from '@vue/test-utils'
import MoviesList from '@/components/MoviesList.vue'
import MovieCard from '@/components/MovieCard.vue'

describe('MoviesList.vue', () => {
  it('renders movies', () => {
    const movies = [
      { id: 1, title: 'Inception', director: 'Christopher Nolan' },
      { id: 2, title: 'Interstellar', director: 'Christopher Nolan' },
      { id: 3, title: 'The Dark Knight', director: 'Christopher Nolan' }
    ]

    const wrapper = shallowMount(MoviesList, {
      propsData: { movies }
    })

    expect(wrapper.findAllComponents(MovieCard).length).toBe(movies.length)
  })
})

In the MoviesList test, we have used the findAllComponents() function, which returns all matching Vue components in the wrapper's children, grandchildren, etc. Therefore this test asserts that the number of MovieCard components equals the number of movies.

Through Vue.js and with the assistance of the Vue Test Utils and Jest, unit testing is not only possible but pleasantly manageable, breaking down our grand production into individual scenes and characters to ensure a blockbuster result. As with any production, the more we rehearse (or test), the better the outcome. Happy testing!

0 Comment


Sign up or Log in to leave a comment


Recent job openings