无法理解的单元测试使用 Jest 导致错误

Art*_*Vic 5 jestjs ngrx ngrx-effects angular

我正在处理两个几乎相同的测试用例,我应该断言期望两个 NgRx 效果返回一个布尔值流。在第一个测试用例中一切都按预期工作,尽管对第二个测试用例执行相同的操作,但我无法使其按预期工作。无论我做什么,收到的值总是一个空数组:

expect(received).toEqual(expected) // deep equality
    - Expected
    + Received

    - Array [
    -   Object {
    -     "frame": 10,
    -     "notification": Notification {
    -       "error": undefined,
    -       "hasValue": true,
    -       "kind": "N",
    -       "value": true,
    -     },
    -   },
    - ]
    + Array []
Run Code Online (Sandbox Code Playgroud)

工作测试

logger.effects.spec.ts:

expect(received).toEqual(expected) // deep equality
    - Expected
    + Received

    - Array [
    -   Object {
    -     "frame": 10,
    -     "notification": Notification {
    -       "error": undefined,
    -       "hasValue": true,
    -       "kind": "N",
    -       "value": true,
    -     },
    -   },
    - ]
    + Array []
Run Code Online (Sandbox Code Playgroud)

logger.effects.ts:

describe('LoggerEffects', () => {
    let actions$: Observable<ApiFailure>;
    let effects: LoggerEffects;
    const serviceMock = <AppLoggerServiceI>{ failure: ({ body, title }) => of(true) };
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [StoreModule.forRoot({})],
            providers: [
                LoggerEffects,
                provideMockActions(() => actions$),
                {
                    provide: 'appLoggerService',
                    useValue: serviceMock
                }
            ]
        });
        effects = TestBed.get(LoggerEffects);
    });
    const failure = new HttpErrorResponse({ error: 'HttpErrorResponse' });
    describe('logApiFailure$', () => {
        it('should return a stream of boolean if the dispatched action is ApiActions.searchFailure', () => {
            const action = ApiActions.searchFailure({ failure });
            actions$ = hot('-a--', { a: action });
            const expected = cold('-b--', { b: true });
            expect(effects.logApiFailure$).toBeObservable(expected);
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

测试失败

router.effects.spec.ts:

logApiFailure$ = createEffect(
        () =>
            this.actions$.pipe(
                ofType(ApiActions.searchFailure),
                exhaustMap(({ failure: { body, title } }) =>
                    this.appLoggerService.failure({
                        body,
                        title
                    })
                )
            ),
        { dispatch: false }
    );
Run Code Online (Sandbox Code Playgroud)

路由器效果.ts:

describe('RouterEffects', () => {
    let actions$: Observable<boolean>;
    let effects: RouterEffects;

    const routerMock = <Partial<Router>>{ navigate: (commands: any[]) => Promise.resolve(true) };

    let router: Router;
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [StoreModule.forRoot({})],
            providers: [
                RouterEffects,
                provideMockActions(() => actions$),
                {
                    provide: Router,
                    useValue: routerMock
                }
            ]
        });
        effects = TestBed.get(RouterEffects);
    });
    describe('navigateTo$', () => {
        it('should return a stream of boolean if the dispatched action is RouterActions.navigateTo', () => {
            const action = RouterActions.navigateTo();
            actions$ = hot('-a--', { a: action });
            const expected = cold('-b--', { b: true });
            console.log('toto', effects.navigateTo$);
            expect(effects.navigateTo$).toBeObservable(expected);
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

在这一点上,我假设 router.effects.spec.ts 中的 Hot Observable 有问题,这阻止了效果调度 navigateTo 操作。你有什么想法吗?

项目的依赖

navigateTo$ = createEffect(
    () =>
        this.actions$.pipe(
            ofType(RouterActions.navigateTo),
            exhaustMap(() => this.router.navigate(['my-route', {}]))
        ),
    { dispatch: false }
);
Run Code Online (Sandbox Code Playgroud)

jkh*_*ley 0

我刚刚花了一些时间跟踪类似的问题(空预期数组),结果发现该问题与 TestScheduler 不管理的异步代码有关。就我而言,我使用的是from([Promise]). 为了解决这个问题,我模拟了返回一个返回 observable 的承诺的函数of()

这个问题对我帮助很大,并且清楚地解释了问题: https ://github.com/cartant/rxjs-marbles/issues/11

在你的情况下,我认为问题是由this.router.navigate(['my-route', {}])返回承诺而不是可观察到的引起的。

尝试嘲笑router.navigate返回of(true)