简体   繁体   English

Angular - 测试 / mocking 订阅使用 rxjs fromEvent

[英]Angular - Testing / mocking subscriptions that use rxjs fromEvent

in my Angular component I have an object array of companies which is provided as via @Input() : When this is loaded (as it is derived from a HTTP request) I take the value and assign it to another variable called filteredList that I use for an *ngFor .在我的 Angular 组件中,我有一个 object 公司数组,它是通过@Input()提供的:当它被加载时(因为它是从 HTTP requestList 派生的)我使用另一个filteredList的变量对于*ngFor

The *ngFor is used in a select menu and I have a @ViewChild which is an HTML Text Input that when a keyup event happens I take the value of the input and filter the filteredList. *ngFor在 select 菜单中使用,我有一个@ViewChild ,它是一个 HTML 文本输入,当发生 keyup 事件时,我获取输入的值并过滤过滤列表。 I am capturing the keyup event using rxJS fromEvent我正在使用 rxJS fromEvent捕获 keyup 事件

To simplify this is my HTML为了简化这是我的 HTML

<input id="companiesInput" #companyInput>

<mat-selection-list (selectionChange)="listBoxChange($event)">
  <mat-list-option
  *ngFor="let company of filteredList"
    [value]="company"
    [checkboxPosition]="'before'">
    {{company.displayName}}
  </mat-list-option>
</mat-selection-list>

and here is some of my component code... all works well!!这是我的一些组件代码......一切正常!

@Input() companyList: any[] = [];
private tagsSubscription: Subscription;
filteredList: any[] = [];

ngOnChanges(changes: any): void {
  if (changes.companyList.currentValue && changes.companyList.currentValue.length > 0) {
    this.filteredList = this.companyList;
  }
}

ngAfterViewInit(): void {
    const tagsSource = fromEvent(this.companyInput.nativeElement, 'keyup').pipe(
      debounceTime(250),
      distinctUntilChanged(),
      switchMap((ev: any) => {
        return of(ev.target.value);
      })
    );

    this.tagsSubscription = tagsSource.subscribe((res: any) => {
      res = res.trim();
      if (res.length > 0) {
        this.filteredList = this.companyList.filter((company) => company.displayName.indexOf(res) > -1);
      } else {
        this.filteredList = this.companyList;
      }
    });
  }

Everything works great, but I need to test my code and this is where I fall short.一切都很好,但我需要测试我的代码,这就是我的不足之处。 Here is my test这是我的测试

describe('tagsSubscription', () => {
    it('should filter the available list of companies returned', () => {
      const dummyArray = [
        { id: 1, displayName: 'saftey io' },
        { id: 2, displayName: 'msa' },
        { id: 3, displayName: 'acme' }
      ];

      component.companyList = dummyArray;

      fixture.detectChanges();
      component.ngOnChanges({ companyList: { currentValue: dummyArray } });

      const fromEventSpy = spyOn(rxjs, 'fromEvent').and.returnValue(() => rxjs.of({}));
      const companiesInput = element.querySelector('#companiesInput');

      element.querySelector('#companiesInput').value = 'ac';
      companiesInput.dispatchEvent(generateKeyUpEvent('a'));
      fixture.detectChanges();

      companiesInput.dispatchEvent(generateKeyUpEvent('c'));
      fixture.detectChanges();

      expect(component.filteredList.length).toEqual(1);
    });
  });

From logging out I can see that in my test the fromEvent is never raised and thus tagsSource.subscribe is never ran.从注销中我可以看到,在我的测试中 fromEvent 从未引发,因此 tagsSource.subscribe 从未运行。 I am doing something wrong, I thought about mocking the fromEvent in my test by adding the following line to the top of my event, like so我做错了什么,我想到了fromEvent在我的测试中的 fromEvent 通过将以下行添加到我的事件顶部,就像这样

const fromEventSpy = spyOn(rxjs, 'fromEvent').and.returnValue(() => rxjs.of('ac')) ; const fromEventSpy = spyOn(rxjs, 'fromEvent').and.returnValue(() => rxjs.of('ac')) ;

this doesn't work either.这也不起作用。 Has anyone any experience of how to test fromEvent Observables with Angular and perhaps can tell me how I can get my test working?有没有人知道如何使用 Angular 测试 fromEvent Observables 的经验,也许可以告诉我如何让我的测试正常工作?

if it's a ViewChild simply trigger it.如果它是ViewChild只需触发它。

const input = fixture.debugElement.query(By.css('#companiesInput'));
input.triggerEventHandler('keyup', {/* some data */});

If it's an input - simply mock it and add 2 methods如果它是一个输入 - 只需模拟它并添加 2 个方法

const handler: Function | undefined;

companyInput.nativeElement.addListener = (eventName: string, eventHandler: Function) => {
  if (eventName === 'keyup') {
    handler = eventHandler;
  }
};
companyInput.nativeElement.removeListener = () => {};

// call your code to subscribe

if (handler) {
  handler('value1');
  handler('value2');
  handler('value3');
  handler('value4');
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM