Vue.js中使用Jasmine测试Watcher的问题排查
解决Vue Watcher测试不触发的问题
我帮你分析下测试代码里的两个核心问题,搞定这俩就能让测试正常跑起来啦:
1. Spy的目标完全错了
你现在用sinon.spy(App, 'value'),但这里的value是组件的props,而watch里的回调函数并不是挂载在组件实例上的方法,所以这个spy根本监听不到watch的触发。你得换个方式来捕获watch的执行:
方案A:把watch逻辑抽成独立方法(推荐)
先调整你的组件代码,把watch里的逻辑抽成一个单独的方法,这样测试时就能直接spy这个方法了:
// 组件代码 export default { props: ['value'], watch: { value(newValue, oldValue) { this.handleValueChange(newValue, oldValue) } }, methods: { handleValueChange(newValue, oldValue) { if (newValue.Status === 'Completed') { // ...你的业务逻辑 } } } }
然后测试代码改成这样:
var propsData = { "value" : { "Status" : "Something" } } it('should trigger watcher when value changes', done => { const Constructor = Vue.extend(App); // spy抽出来的方法 const spy = sinon.spy(App.methods, 'handleValueChange'); const vm = new Constructor({ propsData: propsData }).$mount(); // 替换整个value对象,触发浅监听的watch vm.value = { Status: 'Completed' }; Vue.nextTick(() => { expect(spy.called).to.be.true; // 记得恢复spy,避免影响其他测试 spy.restore(); done(); }) })
方案B:直接spy watch的回调函数
如果不想修改组件代码,也可以直接获取watch里的回调函数来spy:
var propsData = { "value" : { "Status" : "Something" } } it('should trigger watcher when value changes', done => { const Constructor = Vue.extend(App); // 获取watch中value对应的回调函数并spy const watcherCallback = App.watch.value; const spy = sinon.spy(watcherCallback); // 替换原来的watch回调 App.watch.value = spy; const vm = new Constructor({ propsData: propsData }).$mount(); vm.value = { Status: 'Completed' }; Vue.nextTick(() => { expect(spy.called).to.be.true; // 恢复原来的回调 App.watch.value = watcherCallback; done(); }) })
2. 嵌套属性更新无法触发watch的问题
你原来的测试里直接修改vm.value.Status = 'Completed',但Vue的watch默认是浅监听,只会监听value这个引用的变化,不会监听它内部嵌套属性的变化。所以要么像上面那样直接替换整个value对象,要么给watch加上deep: true:
调整组件的watch配置
watch: { value: { handler(newValue, oldValue) { if (newValue.Status === 'Completed') { // ...你的业务逻辑 } }, deep: true // 开启深度监听 } }
这样修改后,你测试里直接改vm.value.Status也能触发watch了,但还是要注意spy的目标要正确哦。
内容的提问来源于stack exchange,提问作者Kutas Tomy
相关产品推荐
相关产品推荐

