Jasmine unit tests - TypeError: Cannot read properties of undefined (reading 'pipe')

Jasmine unit tests - TypeError: Cannot read properties of undefined (reading 'pipe')

TypeError: Cannot read properties of undefined (reading 'pipe') at MyComponent.fetchData

我在 Angular 中 运行 我的 Jasmine 单元测试时遇到上述错误。现有 beforeEach 不喜欢我在 my.component.tsngOnInit() 中的新 fetchData 功能。我在本规范中的所有六个测试都因相同的错误而失败。有什么想法吗?

my.component.ts

export class MyComponent extends BaseComponent implements OnInit {

  constructor(
    private myService: MyService,
  ) {}

  ngOnInit(): void {

    this.fetchData();

  }

  public fetchData() {
        this.myService.getData()
        .pipe(takeUntil(this.unsubscribe$)).subscribe(  //this.unsubscribe$ gets destroyed in BaseComponent's ngOnDestroy(). Only purpose of BaseComponent is to unsubscribe from observables
          data => {
            if (data) {
              return this.myService.getTypesByCategory(data);
            }
          }
        );
    return;
  }

my.service.ts

export class MyService {

  getData(): Observable<any> {
    return this.httpClient.get('https://myurl.com/myquerystring')
    .pipe(this.showError());
  }

  getTypesByCategory(data) {
                
    for (let region of data.regions) {
          return this.selectType(myArg);
    }
  }

  selectType(myArg): void {
       // do stuff
    
  }
  
}

my.component.spec.ts

import { ComponentFixture, TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { Router } from '@angular/router';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { MyService } from 'src/app/my.service';
import { MyComponent } from './mycomponent';

describe('DeviceRegistrationComponent', () => {
  let component: DeviceRegistrationComponent;
  let fixture: ComponentFixture<DeviceRegistrationComponent>;
  let routerSpy: jasmine.SpyObj<Router>;
  let myServiceSpy: jasmine.SpyObj<MyService>;

  beforeEach(
    waitForAsync(() => {
      const myServiceObj = jasmine.createSpyObj('myService', [
        'selectType',
        'getData',
      ]);

      TestBed.configureTestingModule({
        imports: [
          HttpClientTestingModule,
          RouterTestingModule,
          ReactiveFormsModule,
        ],
        declarations: [MyComponent],
        providers: [
          FormBuilder,
          { provide: MyService, useValue: myServiceObj },
        ],
        schemas: [NO_ERRORS_SCHEMA],
      }).compileComponents();


      routerSpy = TestBed.inject(Router) as jasmine.SpyObj<Router>;
      myServiceSpy = TestBed.inject(MyService) as jasmine.SpyObj<MyService>;
      
    }),
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();

    expect(myServiceSpy.selectType).toHaveBeenCalledWith(true);
  });

  // 5 more tests all fail with the same error

});

您的组件需要 getData() 到 return 一个可观察对象,然后向其添加一个 .pipe(...)。默认情况下,间谍对象方法 return undefined。您需要将函数模拟为 return 值

const myServiceObj = jasmine.createSpyObj('myService', [
        'selectType',
        'getData',
      ]);

您也可以模拟 return 值

myServiceObj.getData
  .and
  .returnValue(of(true));