gpt4 book ai didi

Marble 测试中的 Angular NgRx 效果错误 : Expected $. 长度 = 0 等于 2。/预期 $[0] = 未定义等于对象

转载 作者:行者123 更新时间:2023-12-04 12:58:41 37 4
gpt4 key购买 nike

我有一个使用 Angular 和 NgRx 的应用程序,但我很难使用 Marble 测试来测试我的效果。

我得到的错误是:

Expected $.length = 0 to equal 2.
Expected $[0] = undefined to equal Object({ frame: 10, notification: Notification({ kind: 'N', value: LoadOrderLogisticStatusSuccess({ payload: Object({ 1047522: Object({ status: 0, partner: Object({ id: 1, slug: 'loggi' }), eta: '2020-06-09 10:00', pickupEta: '2020-06-09 12:00' }) }), type: 'load-order-logistic-status-success' }), error: undefined, hasValue: true }) }).
Expected $[1] = undefined to equal Object({ frame: 20, notification: Notification({ kind: 'C', value: undefined, error: undefined, hasValue: false }) }).

这是效果:

@Injectable()
export class OrderLogisticStatusEffects {
loadOrdersLogisticStatus$ = createEffect(() =>
this.actions$.pipe(
ofType(LOAD_ORDERS_LOGISTIC_STATUS),
withLatestFrom(this.store$.pipe(select(orderLogisticsStatusPollingIntervalSelector))),
switchMap(([action, pollingInterval]) =>
timer(0, pollingInterval).pipe(
withLatestFrom(this.store$.pipe(select(selectedCompanySelector))),
switchMap(([timerNum, company]) => this.loadOrdersLogisticStatus(pollingInterval, company))
)
)
)
);

constructor(private actions$: Actions, private orderLogisticStatusService: OrderLogisticStatusService, private store$: Store<AppState>) {}

private loadOrdersLogisticStatus(
pollingInterval: number,
company: Company
): Observable<LoadOrderLogisticStatusSuccess | LoadOrderLogisticStatusFail> {
if (!company?.logisticsToken) {
return of(new LoadOrderLogisticStatusFail(new Error('No company selected')));
}

this.orderLogisticStatusService.getOrdersStatus(company.logisticsToken).pipe(
timeout(pollingInterval),
map((result) => new LoadOrderLogisticStatusSuccess(result)),
catchError((error) => {
if (error.name === 'TimeoutError') {
console.warn('Timeout error while loadin logistic status service', error);
} else {
console.error('Error loading order logistic status', error);
Sentry.captureException(error);
}

return of(new LoadOrderLogisticStatusFail(error));
})
);
}
}

这是我的测试:

fdescribe('Order Logistic Status Effect', () => {
let actions$: Observable<Action>;
let effects: OrderLogisticStatusEffects;

describe('With a selected company', () => {
beforeEach(() => {
const mockState = {
ordersLogisticStatus: {
pollingInterval: 10,
},
company: {
selectedCompany: {
logisticsToken: 'ey.xxxx.yyyy',
},
},
};

TestBed.configureTestingModule({
providers: [
{ provide: OrderLogisticStatusService, useValue: jasmine.createSpyObj('orderLogisticsStatusServiceSpy', ['getOrdersStatus']) },
OrderLogisticStatusEffects,
provideMockActions(() => actions$),
provideMockStore({
selectors: [
{
selector: orderLogisticsStatusPollingIntervalSelector,
value: 30,
},
{
selector: selectedCompanySelector,
value: {
logisticsToken: 'ey.xxxx.yyy',
},
},
],
}),
],
});

effects = TestBed.inject<OrderLogisticStatusEffects>(OrderLogisticStatusEffects);
});

it('should sucessfully load the orders logistics status', () => {
const service: jasmine.SpyObj<OrderLogisticStatusService> = TestBed.inject(OrderLogisticStatusService) as any;
service.getOrdersStatus.and.returnValue(cold('-a|', { a: mockData }));

actions$ = hot('a', { a: new LoadOrdersLogisticStatus() });
const expected = hot('-a|', {
a: new LoadOrderLogisticStatusSuccess(mockData),
});

getTestScheduler().flush();
expect(effects.loadOrdersLogisticStatus$).toBeObservable(expected);
});
});
});

const mockData = {
1047522: {
status: 0,
partner: {
id: 1,
},
eta: '2020-06-09 10:00',
pickupEta: '2020-06-09 12:00',
},
};


问题似乎发生在我的服务模拟上。即使我将它配置为返回一个冷的 observable,它似乎返回 undefined。

谁能帮我?

堆栈 Blitz : https://stackblitz.com/edit/angular-effects-test

最佳答案

StackBlitz .

有几个问题:

首先,loadOrdersLogisticStatus错过了返回:

loadOrdersLogisticStatus (/* ... */) {
return this.orderLogisticStatusService.getOrdersStatus(/* ... */)
}

然后,我发现 jasmine-marbles不设置 AsyncScheduler.delegate自动,而不是 TestScheduler.run :

 run<T>(callback: (helpers: RunHelpers) => T): T {
const prevFrameTimeFactor = TestScheduler.frameTimeFactor;
const prevMaxFrames = this.maxFrames;

TestScheduler.frameTimeFactor = 1;
this.maxFrames = Infinity;
this.runMode = true;
AsyncScheduler.delegate = this;

/* ... */
}

这很重要,因为当使用弹珠时,一切都是 同步 .但是在你的实现中,有一个 timer(0, pollingInterval) observable,默认使用 AsyncScheduler .无设置 AsyncScheduler.delegate ,我们会有异步操作,我认为这是主要问题。

所以,为了设置 delegate属性,我在 beforeEach() 中添加了这一行:

AsyncScheduler.delegate = getTestScheduler();

最后,我认为您的断言存在一个小问题。您的效果属性似乎从未完成,而且您还在使用 timer(0, pollingInterval) .所以我认为你现在可以做的是添加 take(N)运算符,以便针对 N 进行测试排放:

it("should sucessfully load the orders logistics status", () => {
const service: jasmine.SpyObj<OrderLogisticStatusService> = TestBed.inject(OrderLogisticStatusService) as any;
service.getOrdersStatus.and.callFake(() => cold('-a|', { a: mockData }));

actions$ = hot('a', { a: new LoadOrdersLogisticStatus() });
const expected = hot('-a--(b|)', {
a: new LoadOrderLogisticStatusSuccess(mockData),
b: new LoadOrderLogisticStatusSuccess(mockData),
});

expect(effects.loadOrdersLogisticStatus$.pipe(take(2))).toBeObservable(expected);
});
'-a--(b|)' - a在第 10 帧发送, b + complete通知(由于 take )发送至 40th框架,因为 pollingInterval30并且当前帧将是 10何时安排第二个通知( b )。

关于Marble 测试中的 Angular NgRx 效果错误 : Expected $. 长度 = 0 等于 2。/预期 $[0] = 未定义等于对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62293723/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com