ค้นหาเว็บไซต์

angular - การทดสอบหน่วย Jasmine - TypeError: ไม่สามารถอ่านคุณสมบัติของ undefined (กำลังอ่าน 'pipe')


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

ฉันได้รับข้อผิดพลาดด้านบนเมื่อรันการทดสอบหน่วย Jasmine ของฉันใน Angular beforeEach ที่มีอยู่ไม่ถูกใจฟังก์ชัน fetchData ใหม่ของฉันใน ngOnInit() ของ my.component.ts การทดสอบทั้งหกในสเปกนี้ล้มเหลวด้วยข้อผิดพลาดเดียวกัน มีใครพอจะแนะนำได้ไหม?

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

});

คำตอบ #1

คอมโพเนนต์ของคุณคาดว่า getData() จะต้องคืนค่า observable ซึ่งมันจะนำไปเพิ่ม .pipe(...) ด้วย โดยค่าเริ่มต้น เมธอดของวัตถุสปายจะคืนค่า undefined คุณจำเป็นต้องจำลองฟังก์ชันเพื่อให้คืนค่า

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

คุณสามารถจำลองค่าที่ส่งกลับได้เช่นกัน

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