【问题标题】:How to unit test this effect (with {dispatch: false})?如何对这种效果进行单元测试(使用 {dispatch: false})?
【发布时间】:2018-06-27 08:04:52
【问题描述】:

ngrx 和单元测试初学者在这里。我有以下效果:

@Injectable()
export class NotificationEffects {
  @Effect({dispatch: false})
  notificationShow$ = this.actions$
    .ofType(notificationAction.NOTIFICATION_SHOW)
    .do((action: notificationAction.NotificationShowAction) => {
      this.notificationService.info(action.payload.config);
    });

  constructor(private actions$: Actions, private notificationService: NotificationService) {}
}

具体来说,我想测试一下notificationService方法info是否被调用了。我该怎么做?

我遵循了这些示例,但没有找到解决方案:

https://netbasal.com/unit-test-your-ngrx-effects-in-angular-1bf2142dd459 https://medium.com/@adrianfaciu/testing-ngrx-effects-3682cb5d760e https://github.com/ngrx/effects/blob/master/docs/testing.md

【问题讨论】:

    标签: angular unit-testing ngrx-effects


    【解决方案1】:

    如果有人感兴趣但没有明确订阅效果并且只使用jasmine-marbles

    it('should call a notification service method info with a payload', () => {
        actions$ = cold('a', { a: new notificationAction.NotificationShowAction(payload) });
        
        // `toBeObservable` will subscribe the effect and does the trick
        expect(effects.notificationShow$).toBeObservable(actions$);
        expect(service.info).toHaveBeenCalledWith(payload);
      });
    

    【讨论】:

      【解决方案2】:

      最简单(官方建议)的方法是这样做:

          it('should navigate to the customers detail page', () => {
            actions$ = of({ type: '[Customers Page] Customer Selected', name: 'Bob' });
      
            // create a spy to verify the navigation will be called
            spyOn(router, 'navigateByUrl');
      
            // subscribe to execute the Effect
            effects.selectCustomer$.subscribe();
      
            // verify the navigation has been called
            expect(router.navigateByUrl).toHaveBeenCalledWith('customers/bob');
          });
      

      这里是the source

      【讨论】:

        【解决方案3】:
        it('should call a notification service method info with a payload', () => {
            actions$ = cold('a', { a: new notificationAction.NotificationShowAction(payload) });
            effects.notificationShow$.subscribe(() => {
              expect(service.info).toHaveBeenCalledWith(payload);
            });
          });
        

        它运作良好,但问题是发生错误时。在这种情况下,错误不会报告给测试运行者(在我的情况下是开玩笑的)。我需要添加 try catch 块来获取错误:

           it('should call a notification service method info with a payload', () => {
                actions$ = cold('a', { a: new notificationAction.NotificationShowAction(payload) });
                effects.notificationShow$.subscribe(() => {
                    try {
                        expect(service.info).toHaveBeenCalledWith(payload); 
                    } catch (error) {
                        fail('notificationShow$: ' + error);
                    }
                });
            });
        

        【讨论】:

        • 至少在开玩笑的情况下,我认为在 JS 测试中通常使用异步代码你需要包装在 fakeAsync 中或在订阅中使用 done 方法,否则它总是会通过
        【解决方案4】:

        所以就这么简单:

        describe('notificationShow$', () => {
          let effects: NotificationEffects;
          let service: any;
          let actions$: Observable<Action>;
          const payload = {test: 123};
        
          beforeEach( () => {
            TestBed.configureTestingModule( {
              providers: [
                NotificationEffects,
                provideMockActions( () => actions$ ),
                {
                  provide: NotificationService,
                  useValue: jasmine.createSpyObj('NotificationService', ['info'])
                }
              ]
            } );
        
            effects = TestBed.get(NotificationEffects);
            service = TestBed.get(NotificationService);
          });
        
          it('should call a notification service method info with a payload', () => {
            actions$ = cold('a', { a: new notificationAction.NotificationShowAction(payload) });
            effects.notificationShow$.subscribe(() => {
              expect(service.info).toHaveBeenCalledWith(payload);
            });
          });
        });
        

        【讨论】:

        • 感谢您的解决方案。我不太清楚什么时候应该在效果中使用冷和热。在上述情况下,冷和热都在工作。
        • 我有完全相同的设置,由于某种原因,订阅块中的代码永远不会被调用。我什至把expect(true).toEqual(false); 放在那里,它永远不会失败。使用ngrx ^7.0.0
        • @codeepic 可能值得创建一个新问题,但如果您不在 describe/it 中包含测试,就会发生这种情况。
        • 我同意上述观点,这不起作用!有效的是上面评论中的问题。您必须以某种方式使用异步,否则测试如何知道它需要等待订阅!
        • 这不是一个很好的例子,因为如果effects.notificationShow$ 根本不发射,那么你永远不会设置expect(service.info)...,所以即使它应该失败也不会失败。
        猜你喜欢
        • 2019-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多