【问题标题】:Test Observable that is piped and uses async pipe测试通过管道传输并使用异步管道的 Observable
【发布时间】:2021-04-05 08:46:22
【问题描述】:

我有以下情况。我有一个 Observable,myObservable$ngOnInit 中初始化。当这种情况发生时,observable 被点击以复制最后一个值以用于其他目的。除此之外,observable 使用async 管道绑定到我的html。如何使用 jasmine karma 测试我的分接功能是否正确运行?

html:

<input [ngModel]="myObservable$ |async">

ts:

ngOnInit():void {
    this.myObservable$ = this.service.getThings()
      .pipe(tap(value=>this.otherProperty=value))
}

在这种情况下,我想测试 this.otherProperty 是否真正具有值。我该如何测试?

【问题讨论】:

  • 模拟你的服务调用 this.service.getThings() 返回一个 Observable 产生一些值 - 然后你的测试断言 this.otherProperty 等于那个值。对此有很多已回答的问题,我将尝试找到一个。
  • 我试过了,使用const mySpy = spyOn (mockService, 'getThings').and.returnValue(of[4]))。在这种情况下,我收到错误 Expected undefined to equal 4
  • 我的预感是它与缺少订阅有关 - 因为订阅只是由于async 管道而发生的,这不是测试范围的一部分,如何正确测试它?
  • 您可以在测试文件 myObservable$ 中手动订阅,并在订阅块中添加期望
  • 谢谢!在测试中订阅 myObservable$ 解决了我的问题

标签: angular typescript rxjs jasmine karma-jasmine


【解决方案1】:

您应该将 spy 安装到 this.service.getThings() 方法上并返回一个同步的 observable,其值立即可用。然后,您可以在组件的ngOnInit 方法上订阅它。最后,对otherProperty 进行断言以检查该值。欲了解更多信息,请参阅Component with async service

例如使用angular v11+

example.component.ts:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { ExampleService } from './example.service';

@Component({
  selector: 'app-example',
  template: '<input [ngModel]="myObservable$ |async">',
})
export class ExampleComponent implements OnInit {
  myObservable$: Observable<string>;
  otherProperty: string;
  constructor(private service: ExampleService) {}

  ngOnInit() {
    this.myObservable$ = this.service
      .getThings()
      .pipe(tap((value) => (this.otherProperty = value)));
  }
}

example.service.ts

import { Injectable } from '@angular/core';
import { of } from 'rxjs';

@Injectable()
export class ExampleService {
  constructor() {}
  getThings() {
    return of('your real implementation');
  }
}

example.component.spec.ts:

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { of } from 'rxjs';
import { ExampleComponent } from './example.component';
import { ExampleService } from './example.service';

fdescribe('65479995', () => {
  let fixture: ComponentFixture<ExampleComponent>;
  let component: ExampleComponent;
  let exampleServiceSpy: jasmine.SpyObj<ExampleService>;
  beforeEach(
    waitForAsync(() => {
      exampleServiceSpy = jasmine.createSpyObj('ExampleService', ['getThings']);
      exampleServiceSpy.getThings.and.returnValue(of('fake implementation'));

      TestBed.configureTestingModule({
        declarations: [ExampleComponent],
        imports: [FormsModule],
        providers: [{ provide: ExampleService, useValue: exampleServiceSpy }],
      })
        .compileComponents()
        .then(() => {
          fixture = TestBed.createComponent(ExampleComponent);
          component = fixture.componentInstance;
        });
    })
  );
  it('should pass', () => {
    expect(component.otherProperty).toBeUndefined();
    fixture.detectChanges();
    expect(component.otherProperty).toBe('fake implementation');
    expect(exampleServiceSpy.getThings).toHaveBeenCalled();
  });
});

测试结果:

================================================================================
✔ Browser application bundle generation complete.
✔ Browser application bundle generation complete.
Chrome Headless 80.0.3987.87 (Mac OS 10.13.6): Executed 2 of 47 (skipped 45) SUCCESS (0.17 secs / 0.063 secs)
TOTAL: 2 SUCCESS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 2019-08-02
    相关资源
    最近更新 更多