Hi, I have this component:
<template>
<div></div>
</template>
<script>
export default {
name: 'Foo',
data() {
return {};
},
created() {
this.$store.dispatch('SOME_ACTION');
},
};
</script>
<style scoped></style>
and this test:
import jest from 'jest';
import Vuex from 'vuex';
import {
createLocalVue,
shallow,
} from 'vue-test-utils';
import Foo from '@/components/Foo';
const localVue = createLocalVue();
localVue.use(Vuex);
describe.only('Foo.vue', () => {
let actions;
let store;
beforeEach(() => {
actions = {
SOME_ACTION: jest.fn()
};
store = new Vuex.Store({
state: {},
actions
});
});
it('should dispatch action when created', () => {
shallow(Foo, {
localVue,
store
});
expect(actions.SOME_ACTION).toHaveBeenCalled();
});
});
If I'm not missing anything, this is the same structure as the one used here.
But when I run jest, I get this:
FAIL src/__tests__/components/Foo.spec.js
● Console
console.error node_modules/vue/dist/vue.runtime.common.js:432
[Vue warn]: Error in created hook: "TypeError: Cannot read property 'dispatch' of undefined"
[...]
● Foo.vue › should dispatch action when created
TypeError: _jest2.default.fn is not a function
at Object.<anonymous> (src/__tests__/components/Foo.spec.js:19:35)
● Foo.vue › should dispatch action when created
TypeError: Cannot read property 'SOME_ACTION' of undefined
at Object.<anonymous> (src/__tests__/components/Foo.spec.js:32:19)
I'm using [email protected].
Thanks.
Some clarification: I'm guessing the problem is with Vuex mocking because of the Cannot read property 'dispatch' of undefined message. I added a log before the this.$store.dispatch and this.$store was indeed undefined.
The other two messages are worrisome too, jest.fn should be a function for sure, but I'm not sure if they are related with the store problem.
Hi, thanks for your interest but Github issues are for bug reports and feature requests only. You can ask questions on the forum, the Discord server, gitter or StackOverflow.
It looks like the error is thrown because you're trying to access a property on an object that isn't defined. You can read about hot to test Vuex in using with Vuex.
Hi, I wasn't asking a question. I understand how Vuex is supposed to be tested, I even referenced the "Using with Vuex" section in my first comment.
I'll double check that there are no mistakes on my side, but I wanted to clarify that this is, from my perspective, a bug report.
same issue ... did you solved it ? nothing on this topic in StackOverflow ( I posted an issue ..)
Hello @erwin16. In my case, the problem was that I was requiring Jest (const jest = require('jest')) and then using that for mocking the actions in the before hook. I had to use the injected global instead. But errors thrown in the before hooks don't prevent tests from running, and that made me believe that the issue was with vue-test-utils (it wasn't).
@fvictorio hi! Could you post working example please? I'm stuck with exactly this error for 2 days already.
Thank you @fvictorio this fixed my problem.
I had to use the injected global instead.
@frutality did you solve this? My app is working, but my test is failing due to no $store on this. I did not import jest and use the injected jest instead, but I still have this issue.
@Anima-t3d honestly, can't remember. I refused to write tests for vuex-related components. It feels wrong. Only writing tests for simple components.
This is what worked for me:
<template>
<div></div>
</template>
<script>
export default {
name: 'Foo',
data() {
return {};
},
created() {
this.$store.dispatch('SOME_ACTION');
},
};
</script>
<style scoped></style>
// note no import of jest
import Vuex from 'vuex';
import {
createLocalVue,
shallow,
} from 'vue-test-utils';
import Foo from '@/components/Foo';
// add the 2 lines below
const localVue = createLocalVue();
localVue.use(Vuex);
describe.only('Foo.vue', () => {
// add the 2 lines below
let actions;
let store;
// add this before each
beforeEach(() => {
actions = {
SOME_ACTION: jest.fn()
};
store = new Vuex.Store({
state: {},
actions
});
});
it('should dispatch action when created', () => {
// I forgot to add localVue and store
shallow(Foo, {
localVue,
store
});
// change expecting a result to expect the action to be called.
expect(actions.SOME_ACTION).toHaveBeenCalled();
});
});
@Anima-t3d : I tried the way you have suggested for a component calling a store dispatch . Still am getting the same error 'this.$store.dispatch is not a function'. Any other alternative ??
@arun045 Can you put your code here? Meanwhile, did you see This.$store.dispatch() is undefined Vuex?
Also had the same issue but was able to fix it with this approach:
-- MyComponent.spec.js --
import { shallowMount } from '@vue/test-utils'
import store from '@/store'
import router from '@/router'
import MyComponent from '@/components/MyComponent'
describe('MyComponent', () => {
const wrapper = shallowMount(MyComponent, {
router,
store,
})
it('render without crashing', () => {
...
})
})
-- store.js --
import Vue from 'vue'
import Vuex from 'vuex'
const test = {
namespaced: true,
state: { ... },
getters: { ... },
actions: { ... },
mutations: { ... },
}
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
modules: {
test,
},
strict: debug,
});
-- router.js --
import Vue from 'vue'
import VueRouter from 'vue-router'
import MyComponent from '@/components/MyComponent'
const routes = [
{ path: '/', name: 'My Component', component: MyComponent },
]
Vue.use(VueRouter)
export default new VueRouter({
mode: 'history',
routes,
})
Most helpful comment
This is what worked for me: