How to test Nuxt.js asyncData and fetch hooks

How to test Nuxt.js asyncData and fetch hooks

This article is more than four years old. The content may be outdated, especially technical examples or references to tooling.

When you set up a project with create-nuxt-app or configure it manually, you may also add a framework for unit testing. @vue/test-utils provides utilities for mounting Vue components and inspecting their behaviour.

Testing Nuxt-specific hooks requires some additional care. This article looks at calling hooks directly in a unit test and explains what that approach does, and does not, verify.

Testing a Vue component

A basic component test only takes a few lines. Mount the component, inspect its initial state, call a method and check the result. With shallowMount, child components are stubbed so the test can focus on the component itself.

import { shallowMount } from '@vue/test-utils';
import ExampleComponent from './example-component.vue';

describe('Example component', () => {
  it('should test something', () => {
    const wrapper = shallowMount(ExampleComponent);
    expect(wrapper.vm.anyProp).not.toEqual(anyExpectedValue);
    wrapper.vm.myMethod();
    expect(wrapper.vm.anyProp).toEqual(anyExpectedValue);
  });
});

This test checks how the component's state changes after a method call. The assertions should describe the behaviour you expect from that component.

Testing a Nuxt.js component

Nuxt adds features such as asyncData, fetch and head to the component options. These features normally run within Nuxt's runtime. Mounting a component with Vue Test Utils alone does not reproduce that runtime.

For a focused unit test, you can call a hook directly. That gives you control over its execution and the inputs used by the test.

Calling a hook directly

import ExampleComponent from './example-component.vue';

describe('Example component', () => {
  it('should test something', async () => {
    await ExampleComponent.asyncData();
    expect(something).toEqual(somethingExpected);
  });
});

This calls the function without mounting the component. You can make assertions about its return value or calls to mocked dependencies. It does not show how Nuxt integrates the result into a rendered page.

Passing an explicit context

JavaScript's Function.prototype.call() lets you choose the this value for a function call. Its first argument supplies that value; the remaining arguments are passed to the function:

call(thisArg, arg1, ... , argN);

The following example mounts the component and passes wrapper.vm as the this value for the direct call. Assertions then inspect the mounted component's state:

import { shallowMount } from '@vue/test-utils';
import ExampleComponent from './example-component.vue';

describe('Example component', () => {
  it('should test something', async () => {
    const wrapper = shallowMount(ExampleComponent);
    expect(wrapper.vm.anyProp).not.toEqual(anyExpectedValue);
    await ExampleComponent.asyncData.call(wrapper.vm);
    expect(wrapper.vm.anyProp).toEqual(anyExpectedValue);
  });
});

What these unit tests verify

A direct call tests the function under the conditions you supply. Depending on the assertions, that can cover returned data, calls to mocked dependencies or changes to the state provided by the test.

It does not verify that Nuxt invokes the hook with those same conditions. In particular, these examples do not test:

  • When and how Nuxt runs hooks during its lifecycle.
  • Server-side rendering, hydration or route navigation.
  • Nuxt's automatic handling of loading and error states.

For those behaviours, add integration or end-to-end tests that run the application through Nuxt. Use direct unit tests for focused checks of function behaviour, and test the complete page separately when the result depends on the framework's runtime.

Comments

There are no comments yet, leave yours below.

Leave a comment

Do you have an addition, question or experience related to this article? Share it below.

Comments are briefly reviewed before they appear.

Read more about:

Starten met unit testen in Vue

Frontendlogica in Vue kun je ook met unit tests controleren. Aan de hand van een klein component bouwen we een test op met Jasmine en Karma: het component laden, afzonderlijk gedrag herkennen en testgevallen kiezen. Daarbij kijken we naar verschillende invoerwaarden en grenzen, zodat de test meer doet dan alleen de code uitvoeren.

Lees verder

Unit testen van private methods in Angular

Hoe test je logica in een private Angular-method zonder die alleen voor een test public te maken? Dit artikel bespreekt testen via publiek gedrag, het verplaatsen van logica naar een service en een directe benadering wanneer dat niet past. De centrale vraag: wat wil je bewijzen, en hoeveel moet je test daarvoor van de implementatie weten?

Lees verder

The bullshit of code coverage

A test suite can reach 100% coverage and still charge the wrong shipping fee or take a payment twice. Through boundary cases, misleading mocks and missing requirements, I examine what coverage actually proves. The useful question is not whether the code ran, but whether the tests would catch the mistakes your customers care about.

Continue reading