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.