首页 > 解决方案 > 带有参数的 NgRx 选择器未通过单元测试

问题描述

我正在测试我的商店选择器函数是否在我的 ngOnInit() 方法中被正确调用,并且我的带有参数的选择器未通过测试我的不带参数的选择器正在通过(失败的测试在代码示例中注释,它们是最后两个)。错误消息 Expected $[0] = Function to equal Function对我没有帮助。对为什么会发生这种情况的一些见解或只是对ngrx的一般测试调试技巧将不胜感激。

如果需要更多代码,请告诉我。

规格

    fdescribe('OpenOrderAddComponent', () => {
      let component: OpenOrderAddComponent;
      let fixture: ComponentFixture<OpenOrderAddComponent>;
      const modalSpy: jasmine.Spy = jasmine.createSpyObj('ModalController', ['create']);

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [OpenOrderAddComponent],
          schemas: [CUSTOM_ELEMENTS_SCHEMA],
          providers: [
            provideMockStore({
              initialState: INITIAL_APP_STATE()
            }),
            { provide: ModalController, useValue: modalSpy },
          ]
        }).compileComponents();

        fixture = TestBed.createComponent(OpenOrderAddComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      }));

      it('should create', () => {
        expect(component).toBeTruthy();
      });

      describe('on ngOnInit', () => {
        let store: any;
        beforeEach(() => {
          store = fixture.debugElement.injector.get(Store);
          spyOn(store, 'select').and.callThrough();
          component.documentId = 'fakeid';
          component.ngOnInit();
          fixture.detectChanges();
        });

        it('should call select 3 different times', () => {
          expect(store.select).toHaveBeenCalledTimes(3); // succeeds
        });
        it('should select searched items ids', () => {
          expect(store.select.calls.allArgs()[1]).toEqual([getSearchedItemsIds]) // succeeds
        });
        // FAILING TESTS BELOW
        it('should select open order lines', () => {
          expect(store.select.calls.allArgs()[2]).toEqual([getOpenOrderLines(component.documentId)])
          // fails with error: Expected $[0] = Function to equal Function.
        });
        it('should select open order modifications', () => {
          expect(store.select.calls.allArgs()[3]).toEqual([getOpenOrderModifications(component.documentId)])
          // fails with error: Expected $[0] = Function to equal Function.
        });
    });
});

component.ts ngOnInit() 代码

ngOnInit(){    
    this.itemIds$ = this.store.select(getSearchedItemsIds);
    this.store.select(getOpenOrderLines(this.documentId)).subscribe(openOrderLines => {...});
    this.store.select(getOpenOrderModifications(this.documentId)).subscribe(orderModifications =>{...});
}

选择器

export const getSearchedItemsIds = createSelector(
  selectSearch,
  selectItems,
  selectCartLines,
  (searchState, items): string[] => {
    return searchState.search
      .map((itemId: string) => items[itemId].ItemID);
  }
);

export const getOpenOrderLines = (documentId: string) => createSelector(
  selectOpenOrderItems(documentId),
  (orderItems?: OpenOrderItem[]) => {
    return orderItems ? orderItems : undefined;
  }
);

export const getOpenOrderModifications = (documentId: string) => createSelector(
  selectOrderModifications(documentId),
  (orderModifications: OpenOrderModification[]) => {
    return orderModifications;
  }
);

标签: angularjasminengrx

解决方案


我会做这样的事情,!!放置在需要您注意的东西上:

   fdescribe('OpenOrderAddComponent', () => {
      let component: OpenOrderAddComponent;
      let fixture: ComponentFixture<OpenOrderAddComponent>;
      const modalSpy: jasmine.Spy = jasmine.createSpyObj('ModalController', ['create']);

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [OpenOrderAddComponent],
          schemas: [CUSTOM_ELEMENTS_SCHEMA],
          providers: [
            provideMockStore({
              initialState: INITIAL_APP_STATE()
            }),
            { provide: ModalController, useValue: modalSpy },
          ]
        }).compileComponents();

        fixture = TestBed.createComponent(OpenOrderAddComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      }));

      it('should create', () => {
        expect(component).toBeTruthy();
      });

      describe('on ngOnInit', () => {
        let store: any;
        beforeEach(() => {
          store = fixture.debugElement.injector.get(Store);
          spyOn(store, 'select').and.callThrough();
          component.documentId = 'fakeid';
          // component.ngOnInit(); => No need to call `ngOnInit here, the `fixture.detechChanges() below does it for you. Calling it twice can make your assertions fail.
          fixture.detectChanges();
        });

        it('should call select 3 different times', () => {
          expect(store.select).toHaveBeenCalledTimes(3); // succeeds
        });
        it('should select searched items ids', () => {
          expect(store.select.calls.allArgs()[1]).toEqual([getSearchedItemsIds]) // succeeds
        });
        // FAILING TESTS BELOW
        it('should select open order lines', () => {

       expect(store.select).toHaveBeenCalledWith(getOpenOrderLines(component.documentId));
          // !! ^^
          // fails with error: Expected $[0] = Function to equal Function.
        });
        it('should select open order modifications', () => {
          expect(store.select).toHaveBeenCalledWith(getOpenOrderModifications(component.documentId));
          // ^^
          // fails with error: Expected $[0] = Function to equal Function.
        });
    });
});

但我不会断言这store.select是用这个或那个参数调用的。我将测试subscribe每个select.


推荐阅读