Categories
Vue 3 Testing

Testing Vue 3 Apps — Apps with Vuex

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *