如何在StoryBook中Mock子组件以避免外部依赖请求?
问题:Mock子组件阻止动态导入第三方依赖导致的StoryBook运行失败
我在为ParentComponent编写StoryBook时遇到问题:该组件包含ChildComponent子组件,而ChildComponent里通过动态导入common-data-provider的DataProvider组件,这会调用其他仓库代码,导致StoryBook运行失败。
问题代码行:
components: { DataProvider: () => import("common-data-provider"),// --> 问题所在行 }
相关代码示例
ParentComponent的StoryBook代码
import articlesFunds from "../__fixtures__/articles.json"; export default { component: ParentComponent, argTypes: { getConfigFilesDataProvider: { control: "object", }, }, args: { getConfigFilesDataProvider: () => new Promise((resolve) => setTimeout(() => resolve({ data: articlesFunds }))), }, }; export const Default = (args) => ({ components: { ParentComopnent }, props: Object.keys(args), template: ` <ParentComopnent :data-provider="getConfigFilesDataProvider" /> `, });
ChildComponent代码
<template> <DataProvider :data="articles" /> </template> <script> export default { name: "ChildComponent", components: { DataProvider: () => import("common-data-provider"),// --> 问题所在行 ComponentB }, props: { articles: { type: Array, required: true, }, } }; </script>
解决方法
方法1:在Story中直接替换ChildComponent为Mock版本
直接在ParentComponent的Story文件里定义一个Mock的ChildComponent,替换原组件,彻底避免触发动态导入逻辑:
import articlesFunds from "../__fixtures__/articles.json"; import ParentComponent from './ParentComponent.vue'; // 定义Mock的ChildComponent,模拟原组件的props即可 const MockChildComponent = { name: 'ChildComponent', props: ['articles'], // 可以根据需要模拟模板,比如展示传入的articles数据,或者简单占位 template: '<div>Mocked Child Component: {{ articles.length }} items</div>' }; export default { component: ParentComponent, argTypes: { getConfigFilesDataProvider: { control: "object", }, }, args: { getConfigFilesDataProvider: () => new Promise((resolve) => setTimeout(() => resolve({ data: articlesFunds }))), }, }; export const Default = (args) => ({ components: { ParentComponent, ChildComponent: MockChildComponent // 替换原ChildComponent }, props: Object.keys(args), template: ` <ParentComponent :data-provider="getConfigFilesDataProvider" /> `, });
方法2:通过Webpack别名Mock第三方依赖
如果不想修改Story代码,可以在StoryBook的Webpack配置里,把common-data-provider指向本地的Mock组件:
- 修改
.storybook/main.js的Webpack配置:
module.exports = { // 其他原有配置... webpackFinal: async (config) => { config.resolve.alias = { ...config.resolve.alias, // 指向你的Mock DataProvider组件路径 'common-data-provider': require.resolve('../__mocks__/MockDataProvider.vue') }; return config; }, };
- 创建
__mocks__/MockDataProvider.vue:
<template> <div>Mocked Data Provider</div> </template> <script> export default { name: 'DataProvider', props: ['data'] // 匹配原组件的props }; </script>
方法3:全局注册Mock组件覆盖动态导入
在StoryBook的预览配置文件(.storybook/preview.js)中全局注册Mock的DataProvider组件,这样ChildComponent会优先使用全局注册的组件,不会触发动态导入:
import Vue from 'vue'; import MockDataProvider from '../__mocks__/MockDataProvider.vue'; // 全局注册,组件名要和原DataProvider一致 Vue.component('DataProvider', MockDataProvider);
内容的提问来源于stack exchange,提问作者yavgz
相关产品推荐
相关产品推荐

