Vue.js 单元测试 ErrorBoundary
Vue.js unit testing ErrorBoundary
我在 Vue.js 中为我的项目构建了简单的 ErrorBoundary 组件,但我正在努力为其编写单元测试。组件代码如下:
<template>
<div class="overvue-error-boundary">
<slot v-if="!error" />
<div class="error-message" v-else>Something went horribly wrong here.</div>
</div>
</template>
<script>
export default {
data () {
return {
error: false
}
},
errorCaptured (error, vm, info) {
this.error = true;
}
}
</script>
我创建了一个 ErrorThrowingComponent,它会在 created() 生命周期挂钩上引发错误,因此我可以测试 ErrorBoundary:
const ErrorThrowingComponent = Vue.component('error-throwing-component', {
created() {
throw new Error(`Generic error`);
},
render (h) {
return h('div', 'lorem ipsum')
}
});
describe('when component in slot throws an error', () => {
it('renders div.error-message', () => {
// this is when error is when 'Generic error' is thrown by ErrorThrowingComponent
const wrapper = shallowMount(OvervueErrorBoundary, {
slots: {
default: ErrorThrowingComponent
}});
// below code is not executed
expect(wrapper.contains(ErrorThrowingComponent)).to.be.false;
expect(wrapper.contains('div.error-message')).to.be.true;
});
});
问题是 ErrorThrowingComponent 在我尝试实际安装它时抛出错误(因此整个测试失败)。有什么办法可以防止这种情况发生吗?
编辑:我想要实现的是实际上 mount ErrorThrowing 组件在 ErrorBoundary 组件的默认插槽中断言if ErrorBoundary 将呈现错误消息而不是插槽。这是我首先创建 ErrorThrowingComponent 的方式。但我无法断言 ErrorBoundary 的行为,因为我在尝试创建包装器时遇到错误。
对于遇到类似问题的任何人:我已经在 Discord 上的 Vue Land 的#vue-testing 频道上提出了这个问题,他们建议将整个错误处理逻辑移动到一个函数,该函数将从 errorCaptured 调用() hook,然后只测试这个函数。这种方法对我来说似乎很明智,所以我决定 post 在这里。
重构的ErrorBoundary组件:
<template>
<div class="error-boundary">
<slot v-if="!error" />
<div class="error-message" v-else>Something went horribly wrong here. Error: {{ error.message }}</div>
</div>
</template>
<script>
export default {
data () {
return {
error: null
}
},
methods: {
interceptError(error) {
this.error = error;
}
},
errorCaptured (error, vm, info) {
this.interceptError(error);
}
}
</script>
使用 vue-test-utils 进行单元测试:
describe('when interceptError method is called', () => {
it('renders div.error-message', () => {
const wrapper = shallowMount(OvervueErrorBoundary);
wrapper.vm.interceptError(new Error('Generic error'));
expect(wrapper.contains('div.error-message')).to.be.true;
});
});
我在 Vue.js 中为我的项目构建了简单的 ErrorBoundary 组件,但我正在努力为其编写单元测试。组件代码如下:
<template>
<div class="overvue-error-boundary">
<slot v-if="!error" />
<div class="error-message" v-else>Something went horribly wrong here.</div>
</div>
</template>
<script>
export default {
data () {
return {
error: false
}
},
errorCaptured (error, vm, info) {
this.error = true;
}
}
</script>
我创建了一个 ErrorThrowingComponent,它会在 created() 生命周期挂钩上引发错误,因此我可以测试 ErrorBoundary:
const ErrorThrowingComponent = Vue.component('error-throwing-component', {
created() {
throw new Error(`Generic error`);
},
render (h) {
return h('div', 'lorem ipsum')
}
});
describe('when component in slot throws an error', () => {
it('renders div.error-message', () => {
// this is when error is when 'Generic error' is thrown by ErrorThrowingComponent
const wrapper = shallowMount(OvervueErrorBoundary, {
slots: {
default: ErrorThrowingComponent
}});
// below code is not executed
expect(wrapper.contains(ErrorThrowingComponent)).to.be.false;
expect(wrapper.contains('div.error-message')).to.be.true;
});
});
问题是 ErrorThrowingComponent 在我尝试实际安装它时抛出错误(因此整个测试失败)。有什么办法可以防止这种情况发生吗?
编辑:我想要实现的是实际上 mount ErrorThrowing 组件在 ErrorBoundary 组件的默认插槽中断言if ErrorBoundary 将呈现错误消息而不是插槽。这是我首先创建 ErrorThrowingComponent 的方式。但我无法断言 ErrorBoundary 的行为,因为我在尝试创建包装器时遇到错误。
对于遇到类似问题的任何人:我已经在 Discord 上的 Vue Land 的#vue-testing 频道上提出了这个问题,他们建议将整个错误处理逻辑移动到一个函数,该函数将从 errorCaptured 调用() hook,然后只测试这个函数。这种方法对我来说似乎很明智,所以我决定 post 在这里。
重构的ErrorBoundary组件:
<template>
<div class="error-boundary">
<slot v-if="!error" />
<div class="error-message" v-else>Something went horribly wrong here. Error: {{ error.message }}</div>
</div>
</template>
<script>
export default {
data () {
return {
error: null
}
},
methods: {
interceptError(error) {
this.error = error;
}
},
errorCaptured (error, vm, info) {
this.interceptError(error);
}
}
</script>
使用 vue-test-utils 进行单元测试:
describe('when interceptError method is called', () => {
it('renders div.error-message', () => {
const wrapper = shallowMount(OvervueErrorBoundary);
wrapper.vm.interceptError(new Error('Generic error'));
expect(wrapper.contains('div.error-message')).to.be.true;
});
});