如何在 Rxjs 6 中测试 ngrx 管道选择

Ang*_*gad 5 jasmine typescript ngrx angular

以前我可以测试以下商店选择

this.store.select(fromRoot.someselector).pipe(map(r => this.store.dispatch(new Action())));
Run Code Online (Sandbox Code Playgroud)

这是我的测试中的

{provide: Store, useValue: jasmine.createSpyObj('store', ['select']);

store.select.and.returnValue(of({}));
Run Code Online (Sandbox Code Playgroud)

但现在已经变成管道了

this.store.pipe(select(fromRoot.someselector));

this.store.pipe(
        select(fromRoot.someselector), 
        filter(result => !!result), 
        map(r => { 
             if (result === ' hello') { 
               this.store.dispatch(new Action()); 
             } 
           }
        ));
Run Code Online (Sandbox Code Playgroud)

如何测试这一点,特别是当您在选择后有地图并且在其中您正在调度一个操作并且您希望验证操作被调用时。

小智 1

跳过运算符并直接测试流的结果:

store
  .pipe(select('selector'))
  .subscribe(val => expect(val).toBe(theMockedValSentToTheSpy))
Run Code Online (Sandbox Code Playgroud)

进一步解释一下:

  • 创建您商店的模拟
  • 模拟你的价值
  • 在您的模拟商店中返回此模拟值
  • 期望您的组件变量返回模拟值

这给出:

const mockedValue = { id: 1 };
const storeSubjectMock = new BehaviorSubject(mockedValue);
const mockedStore = {
  pipe: () => storeSubjectMock.asObservable(),
};

// { provide: Store, useValue: mockedStore }; in your testbed

it('should return an unaltered value', () => {
  component.variableReferencingStore
    .pipe(select('selector'))
    .subscribe(val => expect(val).toBe(mockedValue))
});
Run Code Online (Sandbox Code Playgroud)

这样做的好处是您可以像这样测试所有运算符。假设你的组件变量是

storeValue$ = this.store.pipe(
  select('selector'),
  map(value => ({ ...value, name: 'customName' }))
)
Run Code Online (Sandbox Code Playgroud)

然后你的测试就变成:

it('should return an altered value with a name property set to customName', () => {
  component.variableReferencingStore
    .pipe(select('selector'))
    .subscribe(val => expect(val).toEqual({ ...mockedValue, name: 'customName'))
});
Run Code Online (Sandbox Code Playgroud)