笑话:模拟 RxJs 管道
Posted
技术标签:
【中文标题】笑话:模拟 RxJs 管道【英文标题】:Jest: mock RxJs pipe 【发布时间】:2019-03-03 02:36:42 【问题描述】:如何模拟更复杂的 RxJs 行为(在 NgRx 的上下文中)?
给定一个简单的组件(SomeComponent):
export class SomeComponent implements OnInit
foo$: Observable<any>;
bar$: Observable<any>;
constructor(private store: Store<State>)
ngOnInit()
this.foo$ = this.store.pipe(select(getFooSelector));
this.bar$ = this.store.pipe(select(getBarSelector));
我想以一种方式模拟商店:
根据传递的选择器,模拟存储返回不同的值。 窥探将哪个参数(选择器)传递给select
运算符。
根据传递的选择器,模拟存储返回不同的值
我会认为它是这样的:
store.pipe = jest.fn(selectOperator =>
switch (selectOperator.arguments[0])
case getFooSelector:
return foo;
case getBarSelector:
return bar;
窥探将什么参数(选择器)传递给select
运算符。
类似的东西:
const spy = jest.spyOn(store, 'pipe');
expect(spy.mock.calls[0]).toHaveBeenCalledWith(select(getFooSelector));
expect(spy.mock.calls[1]).toHaveBeenCalledWith(select(getBarSelector));
总结
我知道这两个示例都是伪代码,但我希望它们能证明我想要实现的目标。如果我的方法完全错误,请对此发表评论。
【问题讨论】:
关于 Ngrx repo 的讨论正在进行中,试图获得官方支持来测试类似的东西。还没有完成,但我已经发布了我现在使用的内容。我使用的是 jasmine,而不是 Jest,但它可能会帮助您构建一个等效的:github.com/ngrx/platform/issues/915#issuecomment-414601899 感谢您的参考。可悲的是,我可以让它们中的任何一个正常工作。你的例子给了我: InvalidPipeArgument: 'function ...' for AsyncPipe 【参考方案1】:使用 NGRX v8.6.0,您应该能够执行以下操作:
let fixture: ComponentFixture<SomeComponent>;
let mockStore: MockStore<State>;
beforeEach(() =>
TestBed.configureTestingModule(
providers: [provideMockStore()],
declarations: [SomeComponent],
);
fixture = TestBed.createComponent(SomeComponent);
mockStore = TestBed.get(Store);
fixture.detectChanges();
);
it('should have a value of foo', done =>
mockStore.overrideSelector(getFooSelector, 'foo');
foo$.subscribe(res =>
done();
expect(res).toBe('foo');
);
);
it('should have a value of bar', done =>
mockStore.overrideSelector(getBarSelector, 'bar');
bar$.subscribe(res =>
done();
expect(res).toBe('bar');
);
);
https://ngrx.io/guide/store/testing
【讨论】:
【参考方案2】:使用RxJs Marbles 使用 NgRx 测试 RxJ。
欲了解更多信息,请阅读RxJS Marble Testing: RTFM 并查看Jest Testing - Jesse Sanders、Reactive Testing Strategies with NgRx - Brandon Roberts & Mike Ryan
实现使用jest.fn().mockImplementationOnce
store.pipe = jest.fn()
.mockImplementationOnce(foo)
.mockImplementationOnce(bar)
expect(store.pipe).toHaveBeenCalledWith(select(getFooSelector));
expect(store.pipe).toHaveBeenCalledWith(select(getBarSelector));
【讨论】:
感谢您的回复。可悲的是,它对我不起作用。我知道它期望Function selectOperator
但得到了... Function selectOperator
。此外,如果我正确理解您的答案,则没有简单的方法可以切换结果。它强烈依赖于调用store.pipe
的顺序。以上是关于笑话:模拟 RxJs 管道的主要内容,如果未能解决你的问题,请参考以下文章
如何使用jasmine-marbles测试rxjs管道中的timeout()
从角度服务通过管道传输时,rxjs catchError 不起作用
我可以将笑话代码覆盖率添加到来自管道的 Bitbucket 拉取请求中的报告吗
RxJs 管道和 lettable 运算符“map”:“void”类型的“this”上下文不可分配给“Observable<>”类型的方法“this”