![](/img/trans.png)
[英]data variable not being updated from watcher on computed property in Vue.js with Vuex
[英]How to test Vue watcher that watches a computed property from VueX?
假设我有以下组件:
import { mapState } from 'vuex';
import externalDependency from '...';
export default {
name: 'Foo',
computed: {
...mapState(['bar'])
},
watch: {
bar () {
externalDependency.doThing(this.bar);
}
}
}
测试时,我想确保externalDependency.doThing()
使用bar
(来自 vuex 状态)调用,如下所示:
it('should call externalDependency.doThing with bar', () => {
const wrapper = mount(Foo);
const spy = jest.spyOn(externalDependency, 'doThing');
wrapper.setComputed({bar: 'baz'});
expect(spy).toHaveBeenCalledWith('baz');
});
Vue test-utils 有一个 setComputed 方法,它允许我当前对其进行测试,但是我不断收到警告说 setComputed 将很快被删除,我不知道还有什么可以测试的:
从你试图实现
测试时,我想确保 externalDependency.doThing() 使用 bar(来自 vuex 状态)调用,如下所示:
(这确实是纯单元测试方法),您可以强制更改此观察者,这基本上是一个函数。 如果计算值或数据值发生变化,则无需跟踪观察者是否发生变化 - 让 Vue 处理它。 因此,要在已挂载的 Vue 实例中更改观察者,只需将其称为
wrapper.vm.$options.watch.bar.call(wrapper.vm)
其中bar
是您的观察者的姓名。 通过这种方式,您将能够测试您要测试的确切功能。
来自此评论https://github.com/vuejs/vue-test-utils/issues/331#issuecomment-382037200 的想法,关于 vue-test-utils 问题,您在问题中提到。
Vue Test Utils文档指出了一种使用非常简单的 Vuex 存储的不同方法:
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
// use a localVue to prevent vuex state from polluting the global Vue instance
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Foo.vue', () => {
let state;
let store;
beforeEach(() => {
// create a new store for each test to prevent pollution
state = { bar: 'bar' };
store = new Vuex.Store({ state });
})
it('should call externalDependency.doThing with bar', () =>
{
shallowMount(MyComponent, { store, localVue });
const spy = jest.spyOn(externalDependency, 'doThing');
// trigger the watch
state.bar = 'baz';
expect(spy).toHaveBeenCalledWith('baz');
});
})
您将需要在 VueX 实例上使用某种 mutator,是的,这确实为测试引入了另一个不相关的单元,但就您个人而言,包括使用 Vuex 在内的测试,该概念已经被打破。
以意想不到的方式修改状态更容易导致与实际使用不同的行为。
您可以直接在源代码处设置该值,即 VueX。 所以你的store.js 中有这样的东西:
const state = {
bar: 'foo',
};
const mutations = {
SET_BAR: (currentState, payload) => {
currentState.bar = payload;
},
};
const actions = {
setBar: ({ commit }, payload) => {
commit('SET_BAR', payload);
},
};
export const mainStore = {
state,
mutations,
actions,
};
export default new Vuex.Store(mainStore);
然后在你的component.spec.js你会这样做:
import { mainStore } from '../store';
import Vuex from 'vuex';
//... describe, and other setup functions
it('should call externalDependency.doThing with bar', async () => {
const localState = {
bar: 'foo',
};
const localStore = new Vuex.Store({
...mainStore,
state: localState,
});
const wrapper = mount(Foo, {
store: localStore,
});
const spy = jest.spyOn(externalDependency, 'doThing');
localStore.state.bar = 'baz';
await wrapper.vm.$nextTick();
expect(spy).toHaveBeenCalledWith('baz');
});
您还可以调用dispatch('setBar', 'baz')
的dispatch('setBar', 'baz')
方法并让突变正确发生,而不是直接设置状态。
NB为每个挂载重新初始化您的状态很重要(即制作一个克隆或重新声明它)。 否则,一个测试可以改变状态,下一个测试将从那个脏状态开始,即使包装器被破坏。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.