【问题标题】:Angular test - observable with different return values角度测试 - 可观察到不同的返回值
【发布时间】:2019-12-31 01:29:10
【问题描述】:

我正在尝试测试一个在她的 ngOnInit 上订阅服务中的 observable 的组件,并根据从 observable 获得的值更改组件的行为。我将我的问题简化为这些代码。

组件:

import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';

@Component({
  selector: 'app-root',
  template: `
  <div>
    <h3>currentValue is {{currentValue}}</h3>
    <div>
      <button (click)="changeTo(true)">true</button>
      <button (click)="changeTo(false)">false</button>
    </div>
  </div>
  `,
  styleUrls: ['./app.component.less']
})
export class AppComponent implements OnInit {
  public currentValue: boolean;

  constructor(
    private appService: AppService
  ) { }

  ngOnInit() {
    this.appService.getObs().subscribe(newValue => this.currentValue = newValue);
  }

  changeTo(value: boolean) {
    this.appService.setObs(value);
  }
}

服务:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class AppService {
    private obs = new BehaviorSubject<boolean>(false);

    getObs(): Observable<boolean> {
        return this.obs.asObservable();
    }

    setObs(value: boolean): void {
        this.obs.next(value);
    }
}

测试:

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { of } from 'rxjs';

describe('AppComponent', () => {
  let mockAppService = jasmine.createSpyObj(['setObs', 'getObs']);

  let app: AppComponent
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      providers: [
        { provide: AppService, useValue: mockAppService }
      ]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    mockAppService.getObs.and.returnValue(of(false));
    app = fixture.debugElement.componentInstance;
    fixture.detectChanges();
  });

  it('should create the app', () => {

    expect(app).toBeTruthy(); // pass
  });

  it('should set currentValue to false', () => {

    expect(app.currentValue).toBe(false); // pass
  });

  it('should change currentValue to true', () => 
    mockAppService.// some how to do next(true)
    fixture.detectChanges();

    expect(app.currentValue).toBe(true); // 
  });
});

我希望有一种简单的方法来控制 mockObservable 返回的值。我想更改测试之间的值并测试每个选项。

我看到了 jasmine-marbles 选项,但对于这样的问题,它看起来很复杂。有人知道一种简单的方法吗?

编辑:我希望能够在 observale 上调用 next(),而不调用 setObs(假设它是私有的,实际上在我的应用程序中我没有 setObs 函数,对 next() 的调用更多复杂函数)

【问题讨论】:

    标签: angular jasmine


    【解决方案1】:

    您的组件在ngOnInit() 中调用getObs()。您的测试在 beforeEach 块中调用 fixture.detectChanges()。第一次调用detectChanges() 会导致调用ngOnInit()。

    所以在测试中改变getObs() 的行为不会改变任何东西。太晚了。在执行 beforeEach 块之前,组件已经调用并订阅了它。

    将调用移动到第一个fixture.detectChanges()在测试函数中,并确保存根服务(告诉getObs()必须返回什么)在调用@之前 987654329@.

    【讨论】:

    • 感谢您的回答,但我正在寻找一些稍微不同的东西。我编辑我的问题。我想做类似 next() 的事情来改变测试期间的值,而不仅仅是用不同的值来初始化它
    • 然后模拟 AppService 并将其替换为与您发布的真实实现完全相同的虚假实现:返回一个主题,您可以随时通过调用其 next() 方法来控制它.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2020-09-02
    • 2019-07-26
    相关资源
    最近更新 更多