NgRx 测试 - 检查分派动作的顺序

Ois*_*ley 4 unit-testing mocking jasmine ngrx angular

在运行单元测试并在store.dispatch()函数上创建 Jasmine 间谍时,我正在嘲笑我的 NgRx 存储。
有了这个,我当然能够验证:
一。通过 store.dispatch() 和
b。调用模拟 store.dispatch() 函数的次数。

这可以在以下代码段中看到:

let storeMock;
beforeEach(() => {
  storeMock = {
    dispatch: jasmine.createSpy('dispatch')
  };

  TestBed.configureTestingModule({
    imports: [],
    declarations: [HeaderComponent],
    providers: [
      { provide: Store, useValue: storeMock }
    ]
  });
  TestBed.compileComponents();
});

it(`should dispatch "Loading" and "StoreRecipes" actions when button is clicked`,
      async(() => {
        const fixture = TestBed.createComponent(HeaderComponent);
        fixture.detectChanges();
        const debugElement = queryToGetButton();
        debugElement.nativeElement.click();

        // this works as expected, tests are passing
        expect(storeMock.dispatch).toHaveBeenCalledTimes(2);
        expect(storeMock.dispatch).toHaveBeenCalledWith(
          new RecipeActions.Loading()
        );
        expect(storeMock.dispatch).toHaveBeenCalledWith(
          new RecipeActions.FetchRecipes()
        );
      })
 );
Run Code Online (Sandbox Code Playgroud)

但是,我想知道是否有一种方法可以验证调度操作的顺序?

上面只是一个简单的单元测试示例,但如果稍后运行集成测试,我想有一种方法来验证不同操作的调度顺序会很有用。

我曾尝试直接访问调度模拟上的“调用”列表(就像可以在 Jest 中完成),但我猜这在 Jasmine 中不受支持(在 storeMock.dispatch 上调用 .something 时没有得到任何智能感知建议下一行)

expect(storeMock.dispatch.calls).toEqual([
  [new RecipeActions.Loading()], // First call
  [new RecipeActions.FetchRecipes()]  // Second call
]);
Run Code Online (Sandbox Code Playgroud)

我无法在 NgRx 的主要文档、StackOverflow 上或通过任何其他方式找到与此相关的任何内容。

我们可以用 Jasmine 验证 NgRx 中调度调用的顺序吗?

任何想法将不胜感激。

Ali*_*F50 5

尝试使用calls.all(). https://daveceddia.com/jasmine-2-spy-cheat-sheet/

it(`should dispatch "Loading" and "StoreRecipes" actions when button is clicked`,
      async(() => {
        const fixture = TestBed.createComponent(HeaderComponent);
        fixture.detectChanges();
        const debugElement = queryToGetButton();
        debugElement.nativeElement.click();

        // this works as expected, tests are passing
        expect(storeMock.dispatch).toHaveBeenCalledTimes(2);
        expect(storeMock.dispatch).toHaveBeenCalledWith(
          new RecipeActions.Loading()
        );
        expect(storeMock.dispatch).toHaveBeenCalledWith(
          new RecipeActions.FetchRecipes()
        );
        // new code
        const allCalls = storeMock.dispatch.calls.all();
        console.log(allCalls);
        const firstCall = allCalls[0].args;
        const secondCall = allCalls[1].args;
        expect(firstCall).toEqual([new RecipeActions.Loading()]);
        expect(secondCall).toEqual([new RecipeActions.FetchRecipes()]); 
      })
 );
Run Code Online (Sandbox Code Playgroud)

使用的替代方法callFake

it(`should dispatch "Loading" and "StoreRecipes" actions when button is clicked`,
      async(() => {
        const fixture = TestBed.createComponent(HeaderComponent);
        fixture.detectChanges();
        const debugElement = queryToGetButton();
        // new code
        let dispatchCount = 0;
        storeMock.dispatch.and.callFake(action => {
          dispatchCount++;
          if (dispatchCount === 1) {
            console.log('first dispatch', action);
            expect(action).toEqual(new RecipeActions.Loading());
          } else {
            console.log('2nd dispatch', action);
            expect(action).toEqual(new RecipeActions.FetchRecipes());
          }
        });
        debugElement.nativeElement.click();

        // this works as expected, tests are passing
        expect(storeMock.dispatch).toHaveBeenCalledTimes(2);
        expect(storeMock.dispatch).toHaveBeenCalledWith(
          new RecipeActions.Loading()
        );
        expect(storeMock.dispatch).toHaveBeenCalledWith(
          new RecipeActions.FetchRecipes()
        );
      })
 );
Run Code Online (Sandbox Code Playgroud)