alfred_jun
alfred_jun

Reputation: 51

Angular ngrx unit test dispatching action in test does not work

I have a component which loads some data from an api, but I only need this data once, so I don't use an reducer and selector for it. I only use the actions and the effects for the api call

Thats the code I want to test:

private loadData() {
    const subscriptions: Subscription = new Subscription();
    subscriptions.add(
      this.actions$
        .pipe(ofType(EApiActions.ApiLoaded))
        .subscribe((action: ApiLoaded) => {
          subscriptions.unsubscribe();
          this.data = action.result;
        })
    );
    subscriptions.add(
      this.actions$
        .pipe(ofType(EApiActions.ApiFailure))
        .subscribe((action: ApiFailure) => {
          subscriptions.unsubscribe();
        })
    );
    this.store.dispatch(
      new ApiRequest()
    );
  }

my test looks like this:

let mockStore: MockStore;

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        provideMockActions(() => actions$),
        provideMockStore({ initialState })
      ],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    mockStore = TestBed.inject(MockStore);
  });

  it('should dispatch action and enter the result|failure actionhandler', () => {
    // Arrange
    const expectedAction = new ApiRequest();
    const dispatchSpy = spyOn(mockStore, 'dispatch');

    // Act
    fixture.detectChanges();

    // Assert
    expect(dispatchSpy).toHaveBeenCalledWith(expectedAction);

    // Act - test success
    mockStore.dispatch(new ApiLoaded([]));
    fixture.detectChanges();

    // Assert
    expect(component.data).not.toBeNull();
  });

the test works till this line expect(dispatchSpy).toHaveBeenCalledWith(expectedAction);

as you can see the component listens to EApiActions.ApiLoaded so i try to dispatch the action with mockStore.dispatch(new ApiLoaded([])); but nothing happens, the code in my component doesnt get executed

How can I solve this? Is this a valid way how I use the actions and effects? or do you think I should always go over a reducer which saves the result to the store and than I can access it with an selector?

Upvotes: 2

Views: 5524

Answers (1)

alfred_jun
alfred_jun

Reputation: 51

Andrei Gătej gave me the hint. Thank you

here is the working test:

it('should dispatch action and enter the result|failure actionhandler', () => {
    // Arrange
    actions$ = of({ type: EApiActions.ApiLoaded });
    const expectedAction = new ApiRequest();
    const dispatchSpy = spyOn(mockStore, 'dispatch');

    // Act
    fixture.detectChanges();

    // Assert
    expect(dispatchSpy).toHaveBeenCalledWith(expectedAction);

    // Act - test success
    mockStore.dispatch(new ApiLoaded([]));
    fixture.detectChanges();

    // Assert
    expect(component.data).not.toBeNull();
  });

Upvotes: 3

Related Questions