【问题标题】:Jest: mock RxJs pipe笑话:模拟 RxJs 管道
【发布时间】: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

标签: angular typescript rxjs jestjs ngrx


【解决方案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 SandersReactive 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 的顺序。
    猜你喜欢
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 2018-10-08
    • 1970-01-01
    相关资源
    最近更新 更多