Testing Vue 3 Apps — Apps with Vuex
Tags: webdev, programming, javascript, vue
Published: 2021-01-26 01:26:15

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


With apps getting more complex than ever, it’s important to test them automatically. We can do this with unit tests, and then we don’t have to test everything by hand.

In this article, we’ll look at how to test Vue 3 apps by writing a simple app and testing it.

### Testing Vuex

We can test apps with a Vuex store.

For example, if we have the following app:

```
import { mount } from '@vue/test-utils'
import { createStore } from 'vuex'

const store = createStore({
  state() {
    return {
      count: 0
    }
  },
  mutations: {
    increment(state) {
      state.count += 1
    }
  }
})

const App = {
  template: `
    <div>
      <button @click="increment" />
      Count: {{ count }}
    </div>
  `,
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment')
    }
  }
}

const app = createApp(App)
app.use(store)
```

We can test it with the real Vuex store.

For example, we can add the test by writing:

```
import { mount } from '@vue/test-utils'
import { createApp } from 'vue'
import { createStore } from 'vuex'

const store = createStore({
  state() {
    return {
      count: 0
    }
  },
  mutations: {
    increment(state) {
      state.count += 1
    }
  }
})

const App = {
  template: `
    <div>
      <button @click="increment" />
      Count: {{ count }}
    </div>
  `,
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment')
    }
  }
}

const app = createApp(App)
app.use(store)

test('vuex', async () => {
  const wrapper = mount(App, {
    global: {
      plugins: [store]
    }
  })
  await wrapper.find('button').trigger('click')
  expect(wrapper.html()).toContain('Count: 1')
})
```

We pass in our `store` into the array we set for the `plugins` property.

Then when we click on the button in `App` , the real store’s state is updated.

### Testing with a Mock Store

We can also test the app with a mock store.

For example, we can write:

```
import { mount } from '@vue/test-utils'
import { createApp } from 'vue'
import { createStore } from 'vuex'

const store = createStore({
  state() {
    return {
      count: 0
    }
  },
  mutations: {
    increment(state) {
      state.count += 1
    }
  }
})

const App = {
  template: `
    <div>
      <button @click="increment" />
      Count: {{ count }}
    </div>
  `,
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment')
    }
  }
}

const app = createApp(App)
app.use(store)

test('vuex using a mock store', async () => {
  const $store = {
    state: {
      count: 25
    },
    commit: jest.fn()
  }
  const wrapper = mount(App, {
    global: {
      mocks: {
        $store
      }
    }
  })
  expect(wrapper.html()).toContain('Count: 25')
  await wrapper.find('button').trigger('click')
  expect($store.commit).toHaveBeenCalled()
})
```

We create our `$store` object with the `commit` method being a mocked function.

Then we get the rendered state.

And we click the button and check that `$store.commit` is called.

This is convenient since we don’t have any external dependencies in our mounted component.

However, if we break the Vuex store, then we don’t have any warnings.

### Conclusion

We can test components that are connected to a Vuex store with Vue 3’s Vue Test Utils.