首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用RxJS弹珠测试角反应形式

用RxJS弹珠测试角反应形式
EN

Stack Overflow用户
提问于 2020-04-17 14:35:23
回答 2查看 798关注 0票数 9

角分量

代码语言:javascript
复制
public setupObservables() {
  this.formFieldChanged$ = this.formField
    .valueChanges
    .pipe(
        debounceTime(100),
        distinctUntilChanged((a, b) => a === b),
    )
}

茉莉花试验

代码语言:javascript
复制
import { of } from 'rxjs';
import { marbles } from 'rxjs-marbles/jasmine';  
...

it('should update value on debounced formField change', marbles(m => {
  const values = { a: "1", b: "2", c: "3" };

  const fakeInputs = m.cold('a 200ms b 50ms c', values);
  const expected = m.cold('100ms a 250ms c', values);

  // works on stackblitz but otherwise gives TS2540 compiler error
  // cannot assign to a read-only property
  component.formField.valueChanges = fakeInputs; 
  component.setupObservables();

  m.expect(component.formFieldChanged$).toBeObservable(expected);
}));

stackblitz.com实例

其目的是使用大理石测试来测试Observable代码的角度反应形式。

  • 这种方法有意义吗?
  • 如何最好地模拟valueChanges对象的FormField
  • 有更好的方法来构造这种测试吗?
EN

回答 2

Stack Overflow用户

发布于 2020-04-25 16:29:28

问题是-你想测试什么。它是单元测试还是e2e测试?如果它是一个单元测试-模拟反应形式,只涵盖你的逻辑,那么你没有问题的valueChanges,因为它是模拟和控制它。

如果这是一个e2e测试-您不应该重新分配valueChanges。任何东西都不应该被模仿/替换,因为它是一个e2e测试。

不过,如果您想要更改valueChanges -使用https://github.com/krzkaczor/ts-essentials#writable

代码语言:javascript
复制
(Writable<typeof component.formField>component.formField).valueChanges = fakeInputs; 

它将使属性类型可写。

如果是单元测试,我个人会投票模拟反应性表单,因为在单元测试中,我们只需要测试单元,它的依赖关系应该被模拟/存根。

我们想要模拟的部件的注入

作为一个选项,您可以将表单作为组件的依赖项移动到组件声明中的提供程序。

代码语言:javascript
复制
@Component({
    selector: 'app-component',
    templateUrl: './app-component.html',
    styleUrls: ['./app-component.scss'],
    providers: [
        {
            provide: 'form',
            useFactory: () => new FormControl(),
        },
    ],
})
export class AppComponent {
    public formFieldChanged$: Observable<unknown>;

    constructor(@Inject('form') public readonly formField: FormControl) {
    }

    public setupObservables(): void {
        this.formFieldChanged$ = this.formField
            .valueChanges
            .pipe(
                debounceTime(100),
                distinctUntilChanged((a, b) => a === b),
            );
    }
}

然后,您可以简单地在测试中注入一个模拟,而不是它。

代码语言:javascript
复制
it('should update value on debounced formField change', marbles(m => {
    const values = { a: "1", b: "2", c: "3" };

    const fakeInputs = m.cold('a 200ms b 50ms c', values);
    const expected = m.cold('100ms a 250ms c', values);

    const formInput = {
        valueChanges: fakeInputs,
    };

    const component = new AppComponent(formInput as any as FormControl);

    component.setupObservables();
    m.expect(component.formFieldChanged$).toBeObservable(expected);
}));
票数 6
EN

Stack Overflow用户

发布于 2021-06-24 09:06:35

使用属性而不是字段是一个更干净的解决方案。

代码语言:javascript
复制
get formFieldChanged$() { return this._formFieldChanged$; }
private _formFieldChanged$: Observable<string>;

...
   
public setupObservables() {
  this._formFieldChanged$ = this.formField
    .valueChanges
    .pipe(
        debounceTime(100),
        distinctUntilChanged((a, b) => a === b),
    )
}

spyOnProperty在这里发挥了魔力,不再需要setupObservables()

代码语言:javascript
复制
it('should update value on debounced formField change', marbles(m => {
  const values = { a: "1", b: "2", c: "3" };

  const fakeInputs = m.cold('a 200ms b 50ms c', values);
  const expected = m.cold('100ms a 250ms c', values);

  spyOnProperty(component, 'formFieldChanged$').and.returnValue(fakeInputs);

  m.expect(component.formFieldChanged$).toBeObservable(expected);
}));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61274166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档