我正在试着写一些关于我在爱奥尼亚的ngrx效果的测试,但没能成功。网上有几个教程,但它们要么不适用于我的案例,要么不适用于depcreated。中的示例
official ngrx migration guide
e、 g.不再工作。
我想测试这样一种情况,其中LoadAllAction由LoadAllAction$effect调度,然后最终调度LoadAllCompleteAction。
这是我的密码。我重命名了类和服务以使其更加清晰,因此如果有拼写错误,请忽略它。导入在实际代码中也是正确的。
我的影响。影响。ts
import {Injectable} from "@angular/core";
import {Actions, Effect} from "@ngrx/effects";
import {catchError, concat, map, switchMap} from "rxjs/operators";
import {Observable} from "rxjs/Observable";
import {IMyObject} from "../models/myObject.model";
import {MyObjectService} from "../../services/myObject.service";
import {
InitMyObjectsCompleteAction,
LOAD_ALL,
LOAD_ALL_COMPLETE,
LoadAllAction,
LoadAllCompleteAction,
SaveMyObjectsCompleteAction, MyObjectsErrorAction
} from "../actions/object.actions";
import {defer} from "rxjs/observable/defer";
import {LogService} from "../../services/log/log.service";
import {ToastService} from "../../services/toast.service";
@Injectable()
export class MyEffects {
constructor(private action$: Actions,
private myObjectService: MyObjectService,
private logService: LogService,
private toastService: ToastService) {
}
@Effect() init$ = defer(() => Observable.fromPromise(this.myObjectService.getSavedMyObjects())
.pipe(
map((favoredObjects: IMyObject[]) => new InitMyObjectsCompleteAction(favoredObjects)),
catchError((error) => this.createErrorObservableAndLog(error)),
concat(Observable.of(new LoadAllAction()))
));
@Effect() loadAllAction$ = this.action$.ofType(LOAD_ALL).pipe(
switchMap(() => this.myObjectService.loadObjects().pipe(
map((favoredObjects: IMyObject[]) => new LoadAllCompleteAction(favoredObjects)),
catchError((error) => {
this.toastService.couldNotUpdateObject();
return this.createErrorObservableAndLog(error)
})
))
);
@Effect() loadAllCompleteAction$ = this.action$.ofType(LOAD_ALL_COMPLETE).pipe(
switchMap((action: LoadAllCompleteAction) => Observable.fromPromise(this.myObjectService.saveObjects(action.favoredObjects))
.pipe(
map(() => new SaveMyObjectsCompleteAction()),
catchError((error) => this.createErrorObservableAndLog(error))
)
)
);
private createErrorObservableAndLog(error){
this.logService.error(error);
return Observable.of(new MyObjectsErrorAction(error))
}
}
模拟。ts
export class MyObjectsServiceMock {
loadMyObjects(): Observable<MyObjects[]> {
return createDummyMyObjectsListObservable();
}
}
export class StorageMock {
get() {
return [];
}
set() {
}
}
export class StoreMock {
private returnMyObjects: boolean = false;
public dispatch() {
return Observable.empty();
}
public select() {
if (this.returnMyObjects)
return createDummyMyObjectsListObservable();
return Observable.empty();
}
public setReturnObjects(wantMyObjects: boolean) {
this.returnMyObjects = wantMyObjects;
}
}
这是目前为止的测试。无论我自己尝试什么样的教程,再加上其他教程,这都是行不通的,我真的很难弄清楚从哪里开始。在下面的示例中,actions没有属性“next”,因为它是可观察的,即使我直接从迁移指南中复制了它。expect()。“Should also work”中的toBe()测试也不正确,但我找不到正确语法的文档。
我的影响。影响。规范ts
import {TestBed} from "@angular/core/testing";
import {MyObjectServiceMock, StorageMock, StoreMock} from "../../../test-config/mocks-ionic";
import {Store} from "@ngrx/store";
import {LogService} from "../../services/log/log.service";
import {MyEffects} from "./myEffects.effects";
import {MyObjectService} from "../../services/myObject.service";
import {provideMockActions} from "@ngrx/effects/testing";
import {Observable} from "rxjs/Observable";
import {cold, hot} from 'jasmine-marbles';
import {InitMyObjectsCompleteAction, LoadAllAction, LoadAllCompleteAction} from "../actions/myObject.actions";
import {Storage} from "@ionic/storage";
import {ToastService} from "../../services/toast.service";
import {ToastController} from "ionic-angular";
import {ReplaySubject} from "rxjs/ReplaySubject";
describe('MyObject Effects', () => {
let myObject: MyObjectEffects;
let actions: Observable<any>;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MyObjectEffects,
provideMockActions(() => actions),
ToastService,
ToastController,
LogService,
{provide: Store, useClass: StoreMock},
{provide: MyObjectService, useClass: MyObjectServiceMock},
{provide: Storage, useClass: StorageMock}
]
})
myObjectEffects = TestBed.get(MyObjectEffects);
});
it('should work', () => {
actions = hot('--a-', {a: InitMyObjectsCompleteAction});
const expected = cold('--b', {b: LoadAllCompleteAction});
expect(myObjectEffects.loadAllCompleteAction$).toBeObservable(expected);
});
it('should work also', () => {
actions = new ReplaySubject(1);
actions.next(new LoadAllAction());
myObjectEffects.loadAllCompleteAction$.subscribe(result => {
expect(result).toBe(new LoadAllCompleteAction());
});
});
});
基本上可以归结为两个问题:
1、如何以正确的方式配置测试台,以及我是否必须
嘲笑一切?
2、如何正确测试
是否按上述和代码中所述调度操作?
很明显,我不是要你为我写测试,但也许你知道我可以从哪里开始,或者给我指出正确的方向。非常感谢,我真的很感激!