Unit Testing Vue Lifecycle Methods

Testing Vue components is incredibly simple. However, lifecycle methods are almost always overlooked.

Unit Testing Vue Lifecycle Methods

Testing Vue components is incredibly simple. However, lifecycle methods are almost always overlooked. While testing lifecycle methods isn't difficult, I haven't found too many resources out there that explain how to do this.

Writing the Component

First, let's say we have a component called MyLifecycleComponent.vue. This component calls an initialize method during the mounted lifecycle step:

<template>
    <div>Hello lifecycle component!</div>
</template>

<script>
export default {
    name: 'MyLifecycleComponent',
    methods: {
        initialize() {
            console.log('initialized');
        }
    },
    mounted() {
        this.initialize();
    }
}
</script>

A very basic test would be to check whether the initialize() method gets called during the mounted() lifecycle.

Writing the Test

By default, lifecycle methods are called automatically while the component is being created, therefore they're supposed to be called only once.

What I want to do is to make the lifecycle methods callable inside the tests. The component instance wrapper.vm does not expose lifecycle methods by default, therefore we need to add them when mounting the component wrapper.

let wrapper;

beforeEach(() => {
    wrapper = shallowMount(MyLifecycleComponent, {
        methods: {
            mounted: MyLifecycleComponent.mounted
        }
    });
});

It's good practice to mount the component before each test in order to have a clean state. As a rule of thumb, it's best to keep things as simple as possible, that's why we're not testing the actual effect of the initialize method, but whether it has been called.

In order to check whether a method has been called, we use jest.spyOn() to create a spy. The spy contains information on whether the method has been called or not, how many times it has been called, and what it has been called with.

import MyLifecycleComponent from '@/components/MyLifecycleComponent';
import { shallowMount } from '@vue/test-utils';

describe('MyLifecycleComponent', () => {
    let wrapper;

    beforeEach(() => {
        wrapper = shallowMount(MyLifecycleComponent, {
            methods: {
                mounted: MyLifecycleComponent.mounted
            }
        });
    });

    describe('mounted()', () => {
        it('should call initialize method', () => {
            const spy = jest.spyOn(wrapper.vm, 'initialize');
            
            wrapper.vm.mounted();
            
            expect(spy).toHaveBeenCalled();
        });
    });
});

Conclusion

Testing lifecycle methods is hassle free when you know how to do it. All of the code presented here can be found in this repository.

When unit testing, I always aim for a 100% test coverage because it keeps me out of trouble when I refactor my code.

 PASS  tests/unit/MyLifecycleComponent.spec.js
  MyLifecycleComponent
    mounted()
      ✓ should call initialize method (27ms)

  console.log src/components/MyLifecycleComponent.vue:10
    initialized

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.051s
Ran all test suites.

Read up next