Angular 单元测试:属性 subscribe 没有访问类型 get

Angular unit test: Property subscribe does not have access type get

尝试 运行 observable 属性 的单元测试,当值出现类型错误时。

运行 我得到的测试: 错误:属性订阅没有访问类型get

我做错了什么? 谢谢你的帮助。

应用-list.component.ts

export class TransferComponent {
    transfers$: Observable<Transfer[] | AppResponseError>;
    constructor(
    private transfersService: TransfersService) {
    this.transfers$ = this.transfersService.transfers$;
  }
}

应用-list.component.spec.ts

it('should hide app-checklist component when return AppResponseError', () => {
    const error : AppResponseError = {
      code:'400',
      message:'Bad request'
    };    
    spyOnProperty(component.transfers$, 'subscribe').and.returnValue(of(error));
    fixture.detectChanges(); 
    expect(fixture.debugElement.query(By.css('app-checklist'))).toBeNull();
  });

来自issue

spyOnProperty is intended for use on objects that have used Object.defineProperty since that is implemented with a function behind it and can't be modified by just assigning to it. If you just have basic properties on an object, you should be able to just assign them.

您可以将存根值分配给 component.transfers$ 属性。

例如

component.ts:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { TransfersService } from './TransfersService';

export type AppResponseError = any;
type Transfer = any;

@Component({
  selector: 'app-transfer',
})
export class TransferComponent implements OnInit {
  transfers$: Observable<Transfer[] | AppResponseError>;
  constructor(private transfersService: TransfersService) {
    this.transfers$ = this.transfersService.transfers$;
  }

  ngOnInit() {
    this.transfers$.subscribe((data) => {
      console.log(data);
    });
  }
}

TransferService.ts:

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

@Injectable()
export class TransfersService {
  transfers$ = of('real observable');
}

component.test.ts:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { AppResponseError, TransferComponent } from './component';
import { TransfersService } from './TransfersService';

fdescribe('65208911', () => {
  let component: TransferComponent;
  let fixture: ComponentFixture<TransferComponent>;
  const transfersServiceStub = {
    transfers$: of(),
  };
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [TransferComponent],
      providers: [
        { provide: TransfersService, useValue: transfersServiceStub },
      ],
    });
    fixture = TestBed.createComponent(TransferComponent);
    component = fixture.componentInstance;
  });
  it('should hide app-checklist component when return AppResponseError', () => {
    const error: AppResponseError = {
      code: '400',
      message: 'Bad request',
    };
    component.transfers$ = of(error);
    fixture.detectChanges();
    // expect(fixture.debugElement.query(By.css('app-checklist'))).toBeNull();
  });
});

单元测试结果:

LOG: Object{code: '400', message: 'Bad request'}
Chrome 80.0.3987.87 (Mac OS 10.13.6): Executed 0 of 15 SUCCESS (0 secs / 0 secs)
WARN: 'Spec '65208911 should hide app-checklist component when return AppResponseError' has no expectations.'
Chrome 80.0.3987.87 (Mac OS 10.13.6): Executed 0 of 15 SUCCESS (0 secs / 0 secs)
Chrome 80.0.3987.87 (Mac OS 10.13.6): Executed 1 of 15 (skipped 14) SUCCESS (0.086 secs / 0.026 secs)
TOTAL: 1 SUCCESS