Find the Vue.js 3 version here.

vue-test-utils is the official testing library for Vue, and will be used throughout the guide. It runs in both a browser and Node.js environment, and works with any test runner. We will be running our tests in a Node.js environment throughout this guide.

vue-cli is the easiest way to get started. It will set up a project, as well as configure Jest, a popular testing framework. Install it by running:

or with npm:

  1. npm install -g @vue/cli

Create a new project by running vue create [project-name]. Choose “Manually select features” and “Unit Testing”, and “Jest” for the test runner.

Once the installation finishes, cd into the project and run yarn test:unit. If everything went well, you should see:

  1. PASS tests/unit/HelloWorld.spec.js
  2. HelloWorld.vue
  3. renders props.msg when passed (26ms)
  4. Test Suites: 1 passed, 1 total
  5. Tests: 1 passed, 1 total
  6. Snapshots: 0 total
  7. Time: 2.074s

Congratulations, you just ran your first passing test!

Writing your first test

We don’t need src/components/HelloWorld.vue or tests/unit/HelloWorld.spec.js anymore, so you can delete those.

Create a Greeting.vue file in src/components. Inside Greeting.vue, add the following:

  1. <template>
  2. <div>
  3. {{ greeting }}
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "Greeting",
  9. data() {
  10. return {
  11. }
  12. }
  13. }
  14. </script>

Writing the test

Greeting has only one responsibility - to render the value. The strategy will be:

  1. render the component with mount
  2. assert that the component’s text contains “Vue and TDD”

Create a Greeting.spec.js inside tests/unit. Inside, import Greeting.vue, as well as mount, and add the outline of the test:

There are different syntaxes used for TDD, we will use the commonly seen describe and it syntax that comes with Jest. describe generally outlines what the test is about, in this case Greeting.vue. it represents a single piece of responsibility that the subject of the test should fulfill. As we add more features to the component, we add more it blocks.

Now we should render the component with mount. The standard practice is to assign the component to a variable called wrapper. We will also print the output, to make sure everything is running correctly:

  1. const wrapper = mount(Greeting)
  2. console.log(wrapper.html())

Run the test by typing yarn test:unit into your terminal. Any file in the tests directory ending with .spec.js is automatically executed. If everything went well, you should see:

  1. PASS tests/unit/Greeting.spec.js
  2. Greeting.vue
  3. renders a greeting (27ms)
  4. console.log tests/unit/Greeting.spec.js:7
  5. <div>
  6. Vue and TDD
  7. </div>

Making assertions

We need to make an assertion to ensure the component is behaving correctly. We can do that using Jest’s expect API. It looks like this: expect(result).to [matcher] (actual).

Matchers are methods to compare values and objects. For example:

  1. expect(1).toBe(1)

A full list of matchers is available in the . vue-test-utils doesn’t include any matchers - the ones Jest provides are more than enough. We want to compare the text from Greeting. We could write:

but vue-test-utils has an even better way to get the markup - wrapper.text. Let’s finish the test off:

  1. import { mount } from '@vue/test-utils'
  2. import Greeting from '@/components/Greeting.vue'
  3. describe('Greeting.vue', () => {
  4. it('renders a greeting', () => {
  5. const wrapper = mount(Greeting)
  6. expect(wrapper.text()).toMatch("Vue and TDD")
  7. })

We don’t need the console.log anymore, so you can delete that. Run the tests with yarn unit:test, and if everything went well you should get:

  1. PASS tests/unit/Greeting.spec.js
  2. Greeting.vue
  3. renders a greeting (15ms)
  4. Test Suites: 1 passed, 1 total
  5. Tests: 1 passed, 1 total
  6. Snapshots: 0 total
  7. Time: 1.477s, estimated 2s

Looking good. But you should always see a test fail, then pass, to make sure it’s really working. In traditional TDD, you would write the test before the actual implementation, see it fail, then use the failing errors to guide your code. Let’s make sure this test is really working. Update Greeting.vue:

  1. <template>
  2. <div>
  3. {{ greeting }}
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "Greeting",
  9. data() {
  10. return {
  11. greeting: "Vue without TDD"
  12. }
  13. }
  14. }
  15. </script>

And now run the test with yarn test:unit:

Next we will look at the two methods vue-test-utils provides to render components: and shallowMount.