Mocking Nuxt Global Plugins to Test a Vuex Store File
Tags: vue, testing, webdev, frontend
Published: 2020-05-06 20:47:31

---
title: Mocking Nuxt Global Plugins to Test a Vuex Store File
published: true
description: How to deal with mocking plugins when you're not mounting a test file
tags: vue, testing, webdev, frontend
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9qojni4llwopl6zzx69h.jpg
---

This is one of those edge cases that drives a developer up the wall, and once it's finally solved you run to The Practical Dev to hopefully spare someone else the pain you went through.

I've written previously about Vue Testing: [VueJS Testing: What Not How](https://dev.to/rdelga80/vuejs-testing-what-not-how-hn4), and since then have become the "go-to" for my company's Vue testing issues.

But this one was quite a head scratcher.

### The Problem

Vue's testing is pretty straight forward thanks to `vue-test-utils`. Testing components is really easy, as long as pieces are properly broken down to units (see my post).

With `vue-test-utils` you can mount components locally within the test file, test against the local mount, and ta-da tests.

Via the mount, and Jest's functionality, things like plugins and mocks can be handled either locally within the file or globally within config or mock files.

This problem, though, has to deal with Vuex Store files which _are not mounted_. This is because state, actions, mutations, and getters are tested directly and not within the Vue ecosystem (which behave differently than if tested directly).

Sample Vuex Store file:

```javascript
export const actions = {
    testAction({ commit }, data) {
        commit('TEST_MUTATION', data)
    }
}

export const mutations = {
    TEST_MUTATIONS(state, data) {
        state.data = data
    }
}
```

Sample Vuex Store test file:

```javascript
import { cloneDeep } from 'lodash-es'
import * as testStore from '@/store/testFile'

describe('@/store/testFile', () => {
    let actions,
        mutations

    const cloneStore = cloneDeep(testStore)

    beforeEach(() => {
        actions = cloneStore.actions
        mutations = cloneStore.mutations
    )}

    it('test action calls test mutation', () => {
        const commit = jest.fn()
        actions.testActions({ commit })

        expect(commit)
            .toHaveBeenCalledWith(
                'TEST_MUTATION',
                expect.anything()
            )
    })
```

### Approaches

This issue circled around a global plugin called `$plugin`, which is a plugin that was created to handle api requests globally.

This means that within the store file there is no imported module, and therefore rules out solutions such as `jest.mock()` or adding a file to the `__mocks__` directory.

This also ruled out adding to `VueTestUtils.config`, since again there is no Vue instance to test against.

Every time the test was run it returned `$plugin` as being undefined.

### Solution

The solution to this problem is actually pretty easy, and I'm a little surprised it took so long to figure out.

Here's an example of what an action like this may look like:

```js
export const actions = {
  async testAction({ commit }) {
    let data

    try {
      data = await this.$plugin.list(`endpoint`)
    } catch (e) {
      console.log(e)
    }

    commit('SET_DATA', data)
  }
}
```

When imported into a test file, it acts as a pure function, without having anything to do with Vuex functionality.

That means that `this` refers to the actions variable, and not a Vue instance!

Once that was cleared up, I added this to the `beforeEach` loop in the test file:

```js
actions.$plugin = {
  list: () => {
    return [{}]
  }
}
```
And that's all. No more failing tests, and no more undefined plugins.