Skip to content
This repository was archived by the owner on Jul 8, 2021. It is now read-only.

Question: Unit testing with the @Select decorator #48

Open
austinvalle opened this issue Mar 12, 2018 · 0 comments
Open

Question: Unit testing with the @Select decorator #48

austinvalle opened this issue Mar 12, 2018 · 0 comments

Comments

@austinvalle
Copy link

Hey @amcdnl , I'm trying to figure out the best way to unit test a service that uses the @Select decorator provided by ngrx-action. Currently I'm using the TestBed from @angular/core, but I'd like to not have to spin up an angular module in order to test the service.

Is there any way we can "mock out" the @Select decorator to avoid having to start up TestBed to test the interactions with the store?

Here is the service I'm trying to unit test:

import { Injectable } from '@angular/core';
import { Select } from 'ngrx-actions';
import { Observable } from 'rxjs/Observable';
import { first } from 'rxjs/operators';

import { Dispatch } from '../../decorators/redux/dispatch';

import { ConfigurationActions } from './configuration.actions';
import { ConfigurationSelectors } from './configuration.selectors';

@Injectable()
export class ConfigurationStateService {

  @Select(ConfigurationSelectors.apiUrl) apiUrl$: Observable<string>;
  @Select(ConfigurationSelectors.adminApiPath) adminApiPath$: Observable<string>;
  @Select(ConfigurationSelectors.httpCallTimeout) httpCallTimeout$: Observable<number>;
  @Select(ConfigurationSelectors.techDiffUnhandledExceptions) techDiffUnhandledExceptions$: Observable<boolean>;
  @Select(ConfigurationSelectors.isConfigurationSet) private isConfigurationSet$: Observable<boolean>;

  @Dispatch() private configurationRequest = ConfigurationActions.onConfigurationRequest;

  onConfigurationRequest = () => {
    this.isConfigurationSet$.pipe(
      first((isLoaded: boolean) => isLoaded === false))
      .subscribe(() => {
         this.configurationRequest();
      });
  }
}

Here is the spec testing that service:

import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { Store, StoreModule } from '@ngrx/store';
import { NgrxActionsModule } from 'ngrx-actions';

import { NgSelect } from '../../decorators/redux/ng-select';
import { ConfigurationState } from '../configuration/models/configuration-state.interface';

import { ConfigurationStateService } from './configuration-state.service';
import { configurationReducer } from './configuration.reducer';
import { ApplicationConfiguration } from './models/application-configuration.interface';
import { OnConfigurationReceived } from './models/on-configuration-received.interface';
import { OnConfigurationRequested } from './models/on-configuration-requested.interface';
import { OnConfigurationResetRequested } from './models/on-configuration-reset-requested.interface';

let store: Store<ConfigurationState>;
let ngSelect: NgSelect;
let appConfig: ApplicationConfiguration;

const initializeDependencies: () => void = () => {
  TestBed.configureTestingModule({
    imports: [
      NgrxActionsModule,
      StoreModule.forRoot({ configurationState: configurationReducer})
    ],
    providers: [
      NgSelect,
      ConfigurationStateService
    ]
  });
  store = TestBed.get(Store);
  ngSelect = TestBed.get(NgSelect);
  ngSelect.connect(store);
};

const createComponent: () => ConfigurationStateService = () => {
  const service = TestBed.get(ConfigurationStateService);
  return service;
};

describe('State Service: Configuration: ', () => {

  beforeEach(() => {
    initializeDependencies();
  });

  describe('with isConfigurationSet = false', () => {
    beforeEach(() => {
      store.dispatch(new OnConfigurationResetRequested());
    });

    it('should dispatch a configuration request', fakeAsync(() => {

      spyOn(store, 'dispatch').and.callThrough();

      createComponent().onConfigurationRequest();
      tick();
      const action = new OnConfigurationRequested();
      expect(store.dispatch).toHaveBeenCalledWith(action);
    }));
  });

  describe('with isConfigurationSet = true', () => {
    beforeEach(() => {
      appConfig = {
        adminApiPath: 'xyz',
        techDiffUnhandledExceptions: true,
        apiUrl: 'zyx',
        httpCallTimeout: 0
      };
      store.dispatch(new OnConfigurationReceived(appConfig));
    });

    it('should not dispatch a configuration request', fakeAsync(() => {
      spyOn(store, 'dispatch').and.callThrough();
      createComponent().onConfigurationRequest();
      tick();
      expect(store.dispatch).not.toHaveBeenCalled();
    }));
  });
});
@austinvalle austinvalle changed the title Unit testing with the @Select decorator Question: Unit testing with the @Select decorator Mar 12, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant