NGXS:如何测试是否已调度动作?

时间:2018-06-28 17:19:12

标签: angular unit-testing ngxs

如何对是否已分派动作进行单元测试?

例如,在LogoutService中,我有以下简单方法:

  logout(username: string) {
    store.dispatch([new ResetStateAction(), new LogoutAction(username)]);
  }

我需要编写一个单元测试,以验证是否已分派了两个操作:

  it('should dispatch ResetState and Logout actions', function () {
    logoutService.logout();

    // how to check the dispactched actions and their parameters?
    // expect(...)
  });

如何检查已调度的动作?

3 个答案:

答案 0 :(得分:2)

正如@Garth Mason所说,您可以检查是否正在使用action streams调用动作。

1。创建变量actions$

describe('control-center.state', () => {
  let actions$: Observable<any>;

  // ...
});

2。使用可观察的

初始化变量actions$
// ...
beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [
      NgxsModule.forRoot([AppState]),
      NgxsModule.forFeature([ControlCenterState])
    ]
  });
  store = TestBed.get(Store);
  actions$ = TestBed.get(Actions);
})
// ...

3。测试是否正在调用动作

使用操作符ofActionsDispatched()函数从流中过滤您的操作,并使用完成的回调。

// ...
it('should call actions ResetStateAction and LogoutAction', async( () => {
  store.dispatch([new ResetStateAction(), new LogoutAction()]);

  actions$.pipe(ofActionDispatched(ResetStateAction, LogoutAction))
  .subscribe((actions) => {
    expect(actions).toBeTruthy();
  });
}));
// ...
  

直到以上对beforeEach的调用中调用完函数,此规范才会启动。并且,只有在完成之前,此规范才能完成。

来自Jasmine documentation

答案 1 :(得分:1)

@Brampage的答案为我返回了误报(angular7,ngxs 3.3)。

还有另一个问题,代码:

ofActionDispatched(ResetStateAction, LogoutAction)

似乎等于“告诉是否已调度ResetStateAction或LogoutAction”。

我尝试过这种方式:

3。测试是否正在调用动作

// ...
it('should call actions ResetStateAction and LogoutAction', async( () => {
  let actionDispatched = false;
  zip(
    actions$.pipe(ofActionDispatched(ResetStateAction)),
    actions$.pipe(ofActionDispatched(LogoutAction))
  )
  .subscribe( () => actionDispatched = true );

  store.dispatch([new ResetStateAction(), new LogoutAction()])
    .subscribe(
      () => expect(actionDispatched).toBe(true)
    );
}));
// ...

答案 2 :(得分:0)

使用茉莉花间谍

我认为,在单元测试中,所有相关依赖项的实际实现都应被模拟,因此我们不应在此处包括任何实际存储。 在这里,我们为Store提供了一个茉莉间谍,并只是检查是否使用正确的参数调度了某些操作。这也可以用来提供存根数据。

describe('LogoutService', () => {
  let storeSpy: jasmine.SpyObj<Store>;

  beforeEach(() => {
    storeSpy = jasmine.createSpyObj(['dispatch']);

    TestBed.configureTestingModule({
      providers: [LogoutService, { provide: Store, useValue: storeSpy }]
    });
  })

  it('should dispatch Logout and Reset actions', () => {
    storeSpy.dispatch.withArgs([
      jasmine.any(ResetStateAction), 
      jasmine.any(LogoutAction)])
     .and
     .callFake(([resetAction, logoutAction]) => {
       expect(resetAction.payload).toEqual({...something});
       expect(logoutAction.payload).toEqual({...somethingElse});
    });

    TestBed.inject(LogoutService).logout();
});