Storybook:在组件级别注入一个模拟的提供者/服务

Posted

技术标签:

【中文标题】Storybook:在组件级别注入一个模拟的提供者/服务【英文标题】:Storybook: Inject a mocked provider/service at component level 【发布时间】:2021-02-23 00:22:31 【问题描述】:

我有一个具有组件级提供程序的 Angular 组件。

@Component(
  selector: 'storybook-di-component',
  templateUrl: './di.component.html',
  providers: [ provide: TEST_TOKEN, useValue: 123 ],
)
export class DiComponent 
  @Input()
  title: string;

  constructor(
    protected injector: Injector,
    protected elRef: ElementRef,
    @Inject(TEST_TOKEN) protected testToken: number
  ) 

在这种情况下,我如何让 storybook 注入不同的提供程序,以便我可以提供替代/模拟服务?比如上面的DiComponent,如果我想注入 provide: TEST_TOKEN, useValue: 456 呢?

现实世界的用例是我正在使用 ngrx/component-store 并且需要为组件提供一个虚拟的、预填充的存储。

(附加信息:) 在模块级别(如下所示)注入它不起作用,因为组件仍在运行并创建它自己的提供者实例:

moduleMetadata: 
        providers: [
             provide: StateStore, useValue: stateStore 
        ],
        imports: [...],
    ,

【问题讨论】:

【参考方案1】:

我最终使用低技术方法解决了这个问题。

    子类化.stories.ts 文件中的组件 在子类中,声明构造函数以注入除需要模拟的服务之外的所有内容。 使用注入服务 + 模拟服务调用 super(...)

鉴于我的实际需要是注入 ngrx/component-store 的模拟,我的 stories.ts 现在有如下内容:

const stateStore = new RecordSuggestionsPageStore(mockSuggestionsService);
stateStore.setState(() => (
    selectableRecords: [
         name: "John Legend", recordType: "employee" ,
         name: "Allan Davies", recordType: "employee" ,
    ]
));

@Component(
    selector: "myapp-suggested-records-page",
    templateUrl: "./suggested-records-page.component.html",
    styleUrls: ["./suggested-records-page.component.scss"]
)
class SuggestedRecordsPageComponentStubbed extends SuggestedRecordsPageComponent 

    constructor(router: Router) 
        super(stateStore, router);
    

【讨论】:

【参考方案2】:

TypeProvider 适合我。对于您的示例,它类似于以下内容,其中 setState 的参数需要与被模拟的方法相匹配:

class MockRecordSuggestionsPageStore implements Partial<RecordSuggestionsPageStore> 
  setState() 
    return [
       name: "John Legend", recordType: "employee" ,
       name: "Allan Davies", recordType: "employee" ,
    ]
  

对于 SuggestedRecordsPageComponent 故事中的提供者

    moduleMetadata: 
      declarations: [...],
      imports: [...],
      providers: [
         provide: StateStore, useClass: MockRecordSuggestionsPageStore 
      ],
    ,

【讨论】:

以上是关于Storybook:在组件级别注入一个模拟的提供者/服务的主要内容,如果未能解决你的问题,请参考以下文章

来自 Storybook 的模拟 api 调用

无法在 NextJs + Storybook 中提供静态文件

如何修复“未捕获的错误:查询不再有模拟响应”

如何在单个故事中模拟窗口变量

使用 Enzyme 进行 Storybook JS 集成测试 - 状态更改被覆盖

用storybook来管理你的UI组件库