Я использую версию NgRx ^ 7.0.0.
Это мой класс эффекта NgRx:
import { Injectable } from '@angular/core';
import { ApisService } from '../apis.service';
import { Effect, Actions, ofType } from '@ngrx/effects';
import { Observable } from 'rxjs';
import { ApisActionTypes, ApisFetched } from './apis.actions';
import { mergeMap, map } from 'rxjs/operators';
@Injectable()
export class ApisEffects {
constructor(private apisS: ApisService, private actions$: Actions) { }
@Effect()
$fetchApisPaths: Observable<any> = this.actions$.pipe(
ofType(ApisActionTypes.FetchApisPaths),
mergeMap(() =>
this.apisS.fetchHardCodedAPIPaths().pipe(
map(res => new ApisFetched(res))
)
)
);
}
И это простой тест. Как вы видите, он должен потерпеть неудачу, но всегда проходит.
Я следовал за подобным вопросом здесь в StackOverflow Как выполнить модульное тестирование этого эффекта (с {dispatch: false})? , но это не работает для меня, как будто выполнение кода никогда не входит в эффекты. $ FetchApisPaths. блок подписки
import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { hot, cold } from 'jasmine-marbles';
import { Observable, ReplaySubject } from 'rxjs';
import { ApisEffects } from '../state/apis.effects';
import { ApisFetch, ApisFetched } from '../state/apis.actions';
import { IApiPath } from '../models';
import { convertPaths, getAPIPathsAsJson, ApisService } from '../apis.service';
import { ApisServiceMock } from './mocks';
describe('Apis Effects', () => {
let effects: ApisEffects;
let actions: Observable<any>;
let apisS: ApisService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ApisEffects,
provideMockActions(() => actions),
{
provide: ApisService,
useClass: ApisServiceMock
}
]
});
effects = TestBed.get(ApisEffects);
apisS = TestBed.get(ApisService);
});
it('should call ApisService method() to get Api Paths', () => {
const spy = spyOn(apisS, 'fetchHardCodedAPIPaths');
const action = new ApisFetch();
actions = hot('--a-', {a: action});
effects.$fetchApisPaths.subscribe(() => {
console.log('%c effect trigerred', 'color: orange; border: 1px solid red;');
// expect(spy).toHaveBeenCalled();
expect(true).toBe(false); // never fails
});
});
});
На случай, если я что-то сделаю глупо с действиями, вот файл действий:
Скорее всего, нет, так как он работает в приложении, как ожидалось.
import { Action } from '@ngrx/store';
import { IApiPath } from '../models';
export enum ApisActionTypes {
FetchApisPaths = '[Apis] Fetch Paths',
FetchedApisPaths = '[Apis] Fetched Paths'
}
export class ApisFetch implements Action {
readonly type = ApisActionTypes.FetchApisPaths;
}
export class ApisFetched implements Action {
readonly type = ApisActionTypes.FetchedApisPaths;
constructor(public payload: IApiPath[]) {}
}
export type ApisActions = ApisFetch | ApisFetched;
======================= EDIT ======================= =======
Я использовал пример из официальных документов ngrx https://ngrx.io/guide/effects/testing и теперь я могу успешно войти в блок подписки ниже, я записываю оба журнала консоли, но тест завершается успешно. Это странно! Я попытался выдать ошибки из блока подписки, и проверка по-прежнему прошла успешно.
it('should work also', () => {
actions$ = new ReplaySubject(1);
actions$.next(new ApisFetch());
effects.$fetchApisPaths.subscribe(result => {
console.log('will be logged');
expect(true).toBe(false); // should fail but nothing happens - test succeeds
console.log(' --------- after '); // doesn't get called, so the code
// execution stops on expect above
});
});