【问题标题】:RxJs/Ngrx TestSheduler with simulated user input (Jasmine)带有模拟用户输入的 RxJs/Ngrx TestSheduler (Jasmine)
【发布时间】:2018-05-31 03:23:13
【问题描述】:

我正在一个 Angular 应用程序中测试 Ngrx 商店效果。作为副作用,我的一个效果有一个使用材质 MatDialog 组件弹出的模态。

我想要做的是运行一个测试,其中效果由一个动作启动,这会触发 mat 对话框出现。然后我想测试单击是/否,然后继续检查结果操作(或缺少操作)。

我们正在使用 rxjs-marbles 来测试我们的商店。

RxJs 似乎并没有大量的示例,但我收集到我需要使用 TestScheduler 来处理这种类型的场景。不过,我不确定它是如何工作的。我正在做大量研究,但没有取得很大进展。

基本上,作为一个弹珠,它看起来像这样:

-a-b-c

其中a 是初始动作,b 是用户在对话框中的点击,c 是结果(c 是可选的,如果用户点击“否”,那么将是没有结果的行动。

我不是要求任何人编写我的代码,只是为我指明正确的方向。我即将开始阅读 TestScheduler 的源代码以更好地理解它,因为我什至不确定在这种情况下是否应该使用它。

基本上,如何编写这样的测试,其中有可观察的流以及使用弹珠模拟的用户输入?

【问题讨论】:

  • 我发现有用的东西(来自今年的 ng-conf):youtube.com/watch?v=dwDtMs4mN48
  • @R.Richards 我看过它,它很有帮助,但它没有说明我如何通过流调用 close() 。我认为调度程序需要参与其中,这并不能很好地以这种方式支持用户交互。回到研究中...如果我找到答案,我会发布答案。

标签: angular jasmine rxjs ngrx jasmine-marbles


【解决方案1】:

所以我意识到我做错了。这是一个单元测试,而不是 e2e 测试,所以我不需要测试 UI 的特定功能。因此,我想出了以下测试:

it('should show a dialog, and do nothing if the user does not confirm',
      () => {
        const dialogRef = jasmine.createSpyObj('dialogRef', {
          afterClosed: of(false),
        });
        const action = new AppActions.PromptUserAction();
        matDialog.open.and.returnValue(dialogRef);

        actions = hot('a', { a: action });
        const expected = cold('', {});

        expect(effects.promptUserAction$).toBeObservable(expected);
        expect(matDialog.open).toHaveBeenCalled();
        expect(dialogRef.afterClosed).toHaveBeenCalled();
      });

解释:

  • 创建一个将由模拟的 MatDialog 服务返回的 dialogRef(在 beforeEach Angular TestBed 设置中完成,通过提供如下所示的间谍对象来创建:

    {
      provide: MatDialog,
      useValue: jasmine.createSpyObj(
        'MatDialog',
        ['open'],
      ),
    },
    
  • 这会存根 open 方法,您会注意到 open 调用是对 returnValue dialogRef 进行的,然后我们可以将其用作间谍来返回我们想要的 observable。真的很简单。

测试的其余部分很简单。希望这对某人有所帮助 - 您不一定需要模拟点击,因为它隐含在流程中!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 2011-10-09
    • 1970-01-01
    • 2016-10-05
    相关资源
    最近更新 更多