Fel*_*ipe 3 unit-testing jasmine angular
我正在使用@ngrx/store和@ngrx/effect开发一个Angular 4应用程序,我正在尝试为我的效果编写一些单元测试.
我的一个效果应该是使用服务从后端获取一些数据.从后端检索值后,应每隔一段时间触发此效果,以生成轮询效果并更新本地数据.
由于轮询间隔是在我的应用程序状态配置的,我希望能够模拟状态存储,以便我可以在测试期间更改它.
这是我的SPEC:
describe('Order Effects', () => {
let actions: Observable<any>;
let effects: OrderEffect;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({ orders: ordersReducer })
],
providers: [
OrderEffect,
provideMockActions(() => actions),
{ provide: OrderService, useValue: jasmine.createSpyObj('orderService', ['getAllOrders']) }
]
});
effects = TestBed.get(OrderEffect);
});
it('should load orders and call load orders complete action', () => {
const mockData = [{ id: 1 }, { id: 2 }, { id: 3 }];
const orderService = TestBed.get(OrderService);
orderService.getAllOrders.and.returnValue(Observable.of(mockData));
actions = hot('--a-', { a: new orderActions.LoadAllOrdersAction(new Date()) });
const expectedEffect = cold('--b|', { b: new orderActions.LoadAllOrdersCompleteAction(mockData) });
expect(effects.loadAllOrders$).toBeObservable(expectedEffect);
});
});
Run Code Online (Sandbox Code Playgroud)
这是效果:
@Injectable()
export class OrderEffect {
@Effect()
loadAllOrders$: Observable<Action> = this.actions.ofType(orderActions.LOAD_ALL_ORDERS)
.withLatestFrom(this.store$) // Get the latest state from the store and add as the second value of the array below
.switchMap((input: any[]) => {
const action: orderActions.LoadAllOrdersAction = input[0];
const store: AppState = input[1];
return Observable.timer(0, store.orders.pollingInterval) // Timer to create the polling effect.
.switchMap(() => this.orderService.getAllOrders(action.payload)
.map((orders: Array<any>) => new orderActions.LoadAllOrdersCompleteAction(orders))
.catch(error => Observable.throw(new orderActions.LoadAllOrdersFailAction(error)))
);
});
constructor(private actions: Actions, private orderService: OrderService, private store$: Store<AppState>) { }
}
Run Code Online (Sandbox Code Playgroud)
在效果代码中,我通过使用以下方式获取当前状态:.withLatestFrom(this.store$)我想模拟此属性:store.orders.pollingInterval.谁能帮我?
小智 9
如果您需要获得效果中的商店状态,则在测试此效果时必须监视商店,以便您可以模拟其状态.
describe('Order Effects', () => {
// ...
let ordersStateMock = {
orders: {
pollingInterval: null
}
};
beforeEach(() => {
const storeSpy = jasmine.createSpyObj('storeSpy', [
'dispatch', 'subscribe'
]);
storeSpy.select = () => Observable.of(ordersStateMock);
// ...
});
});
Run Code Online (Sandbox Code Playgroud)
然后在您所在的州,您可以为商店状态设置所需的值:
it('should load orders and call load orders complete action', () => {
// ...
ordersStateMock.orders.pollingInterval = 2;
actions = hot('--a-', { a: new orderActions.LoadAllOrdersAction(new Date()) });
// ...
});
Run Code Online (Sandbox Code Playgroud)
我在测试中使用此解决方案.我在"使用Angular和ngrx进行反应性编程"一书中得到了它.它指的是ngrx和Angular v2,但它仍然非常有用,因为它解释了反应式编程和关键特性的概念.
希望这可以帮助!
我一直在查看@ngrx文档,我找到了另一个模拟商店状态的可能答案(参见下面的完整代码):
let actions;
let effects: OrderEffect;
let ordersStateMock;
beforeEach(() => {
ordersStateMock = {
orders: {
pollingInterval: 30
}
};
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot(
{ orders: ordersReducer },
{ initialState: ordersStateMock }
)
],
providers: [
OrderEffect,
provideMockActions(() => actions),
{ provide: OrderService,
useValue: jasmine.createSpyObj('orderService', ['getAllOrders'])
}
]
});
effects = TestBed.get(OrderEffect);
});
Run Code Online (Sandbox Code Playgroud)
显然我只需要在StoreModule导入中设置初始状态.
| 归档时间: |
|
| 查看次数: |
6993 次 |
| 最近记录: |