Mocking NgRx store с помощью Spectator

Я пытаюсь писать модульные тесты вместе с Angular, Jest и Spectator. Щас борюсь с издевательским магазином NgRx. Я получаю сообщение об ошибке "Нет поставщика для MockStore" при попытке получить экземпляр предоставленного NgRxMockStore из экземпляра Spectator.

Я прочитал документацию NgRx, касающуюся имитации и модульных тестов, и я могу имитировать хранилище NgRx без использования Spectator, читая документацию, я пробовал поискать в Google помощь, но, похоже, не могу найти примеры совместных издевательств над хранилищем NgRx со Spectator, и я оставил сообщение на NgRx/store Gitter, чтобы узнать, может ли кто-нибудь мне помочь.

Вот как выглядит мой код:

    let component: MyComponent;
    let spectator: Spectator<MyComponent>;
    let mockStore: MockStore<selectors.AppState>;
    let mockUsernameSelector: MemoizedSelector<AppState, string>;

    const createComponent = createComponentFactory({
        component: MyComponent,
        componentProviders: [
            provideMockStore(),
        ],
        shallow: true,
        detectChanges: false,
    });

    beforeEach(() => {
        spectator = createComponent();
        component = spectator.component;
        mockStore = spectator.inject<MockStore<selectors.AppState>>(MockStore);
        mockUsernameSelector = mockStore.overrideSelector(selectors.selectUserName, 'Bob');
    });

Но, как я уже сказал, как только я попытаюсь получить экземпляр MockStore от зрителя через spectator.inject (тоже пробовал spectator.get), Я получаю ошибку "Нет провайдера для MockStore". Я также попытался предоставитьMockStore как это:

    const createComponent = createComponentFactory({
        component: MyComponent,
        componentProviders: [
            mockProvider(MockStore, provideMockStore()),
        ],
        shallow: true,
        detectChanges: false,
    });

Но тогда я, очевидно, получаю ошибку "Нет провайдера для Магазина".

Может быть, здесь кто-нибудь сможет мне помочь? Заранее спасибо!

3 ответа

У меня была такая же проблема, похоже, это работает для меня:

В setup-jest.ts Я определил глобальные инъекции с общим тестовым импортом и поставщиком для магазина, использующего provideMockStore с начальным состоянием:

import { provideMockStore } from '@ngrx/store/testing';

let initialState = MockStoreInitialState; // constant built from all reducers initial states

defineGlobalsInjections({
  imports: [
    MaterialModule,
    NoopAnimationsModule,
    ReactiveFormsModule,
    FormsModule,
    SharedModule,
    TranslateTestingModule.withTranslations({ en: require('./assets/i18n/en.json') }),
  ],
  providers: [provideMockStore({ initialState })],
});

Затем при тестировании компонентов я использую MockStore и шпионы:

describe('SampleCardComponent', () => {
  let mockStore;
  let dispatchSpy;
  let spectator: Spectator<SampleCardComponent>;

  const createComponent = createTestComponentFactory({
    component: SampleCardComponent,
    mocks: [ExperimentTimePipe],
  });

  beforeEach(() => {
    spectator = createComponent({
      props: { sampleHolder: SAMPLE_MOCK },
    });
    mockStore = spectator.get(MockStore);
    dispatchSpy = jest.spyOn(mockStore, 'dispatch');
  });

  test('should create', () => {
    expect(spectator).toBeTruthy();
  });

  test('should call editSample function', () => {
    const handleEditSpy = jest.spyOn(spectator.component, 'handleEdit');

    spectator.click('.button-edit');
    spectator.detectChanges();
    expect(handleEditSpy).toHaveBeenCalled();
    expect(dispatchSpy).toHaveBeenCalledTimes(1);
    expect(dispatchSpy).toHaveBeenCalledWith({//...actionObject})
  });
});

Честно говоря, понятия не имею, лучший ли это способ, но он работает. Если вы видите способ улучшить это, я буду рад это услышать.

Вы можете получить его, просто используя spectator.inject(MockStore).

И не забудьте добавить фиктивное начальное состояние в providerMockStore({ initialState })

      import { Spectator, createComponentFactory } from '@ngneat/spectator';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { mockInitialState } from 'src/mocks/state/app-state.mock';
import { AppComponent } from './app.component';
import { AppState } from './state/app.state';

describe('AppComponent', () => {
  let store: MockStore<AppState>;
  const initialState = mockInitialState;
  let spectator: Spectator<AppComponent>;

  const createComponent = createComponentFactory({
    component: AppComponent,
    declarations: [
      AppComponent,
      ...
    ],
    imports: [...],
    providers: [ provideMockStore({ initialState })],
  });

  beforeEach(() => {
    spectator = createComponent();
    store = spectator.inject(MockStore);
  });

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

  it('check state', () => {
    const isLoggedIn = {
      isLoggedIn: {
        login: true
      },
    };

    const state = {
      ...initialState,
      ...isLoggedIn,
    };

    store.setState(state);
    spectator.fixture.detectChanges();
    expect(spectator.component.isLoggedIn).toBe(true);
  });
});

Вы можете использовать удобную функцию mockProvider.

В массиве провайдеров:

import { createComponentFactory, mockProvider, Spectator, SpyObject } from '@ngneat/spectator/jest';
import { Store } from '@ngrx/store';

providers: [mockProvider(Store)],
Другие вопросы по тегам