使用ngrx中的可观察对象在实际商店中测试选择器

时间:2019-11-19 19:38:08

标签: angular rxjs ngrx

我想编写一个测试,检查分派的动作是否正确修改了状态,结果选择器发出了新值。为了这个问题,我创建了一个简单的示例:

  1. 我派遣了updateDateOfBirth来更新状态
  2. 我想测试选择器是否发出新值
  3. 为此,我创建了一个订阅,并收集了所有发出的值,然后将其与期望的序列进行比较
import { TestBed, async } from '@angular/core/testing';
import { sectionOneFeatureKey } from './section-one.reducer';
import { getReducer } from './section-one.reducer';
import { StoreModule, Store, select } from '@ngrx/store';
import { getDateOfBirth } from './section-one.selectors';
import { State } from './section-one.state';
import { updateDateOfBirth } from './section-one.actions';

fdescribe('section-one selectors', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [StoreModule.forRoot({ [sectionOneFeatureKey]: getReducer() })]
    }).compileComponents();
  }));

  it('should react to store changes', () => {
    const store: Store<State> = TestBed.get(Store);
    const result = [];
    store.pipe(select(getDateOfBirth)).subscribe(x => result.push(x));
    store.dispatch(updateDateOfBirth({ value: 'one' }));
    store.dispatch(updateDateOfBirth({ value: 'two' }));

    // slice(1) to skip initial value
    expect(result.slice(1)).toEqual(['one', 'two']);
  });
});

这种通过subscription&push进行收集的解决方案有效,但是,我想知道是否还有更优雅的方法,例如使用provideMockActions。我尝试使用它,但是显然没有将动作自动分派到商店(这仅对效果有效)。同样,当我将订阅移动到测试的最后一行时,我只会得到最后一个值。我也尝试使用toMatchObservable,但是效果是一样的:我仍然只收到最后发出的值:

expect(store.pipe(select(getDateOfBirth))).toMatchObservable(....)

有没有更好的方法编写这种测试?

1 个答案:

答案 0 :(得分:0)

选择器是纯函数。您可以像调用其他任何函数一样调用它们,并查看它们的结果如何随状态变化而变化。 (请注意,这对于NGRX的V7!V8测试要容易得多:https://ngrx.io/guide/store/testing#testing-selectors

// here I have a function that creates a mock store for me
const createMockStore = (state = initialState) => action => ({
  [SOME_FEATURE_KEY]: someReducer(state, action)
});

describe('SomeFeatureSelectors', () => {
  let storeFactory;

  beforeEach(() => {
    storeFactory = createMockStore(initialState);
  });

  describe('mySelectors', () => {
    it(`should return the error text and set isLoading to false`, () => {
      const state = storeFactory(new fromFeatureActions.SomeActivationFailure('ERROR'));
      const error = fromFeatureQuery.getActivationFailure(state);
      const isLoading = fromFeatureQuery.getActivationLoading(state);
      expect(error).toEqual('ERROR');
      expect(isLoading).toEqual(false);
    });
  });

然后,您可以通过使用新操作和以前的状态调用减速器来“更新”您的状态。然后,您可以再次运行选择器并检查更改。

我希望这会有所帮助。如果您有任何问题,请告诉我。

相关问题