【问题标题】:TypeError: Cannot read properties of undefined (reading 'fetchPersonnelList')类型错误:无法读取未定义的属性(读取 \'fetchPersonnelList\')
【发布时间】:2022-12-01 03:45:47
【问题描述】:

收到错误信息:

TypeError: Cannot read properties of undefined (reading 'fetchPersonnelList')

用我的测试规格。

完整代码:

    import { HttpClientModule } from '@angular/common/http';
import { Component } from '@angular/core';
import {
    async,
    ComponentFixture,
    fakeAsync,
    flush,
    TestBed,
    tick,
} from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ActivatedRoute, Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { SharedModule } from '../../../../../shared/shared.module';
import { PersonnelDataService } from '../services/personnel-data.service';
import { testHFSTaleSchema } from './hfs-table.schema';
import { ListPersonnelComponent } from './list-personnel.component';

const mockPersonnelDataService = {
    list$: of(testHFSTaleSchema.rows),
    fetchPersonnelList: function () {
        return { subscribe: () => this.list$ };
    },
    setPageSize: function () {
        return this.list$;
    },
    fetchPaginatedList: () => {},
};

@Component({
    selector: 'app-details-personnel',
    template: '',
})
export class PersonnelDetailsComponent {}

fdescribe('ListPersonnelComponent', () => {
    let component: ListPersonnelComponent;
    let fixture: ComponentFixture<ListPersonnelComponent>;
    let activatedRoute = { url: {} } as ActivatedRoute;
    let service: PersonnelDataService;
    let router;
    const routes = [
        {
            path: 'personnel-details',
            component: PersonnelDetailsComponent,
        },
    ];

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [
                RouterTestingModule.withRoutes(routes),
                SharedModule,
                BrowserAnimationsModule,
                HttpClientModule,
            ],
            declarations: [ListPersonnelComponent],
            providers: [
                {
                    provide: PersonnelDataService,
                    useValue: mockPersonnelDataService,
                },
                { provide: ActivatedRoute, useValue: activatedRoute },
            ],
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(ListPersonnelComponent);
        component = fixture.componentInstance;
        router = TestBed.inject(Router);
        fixture.detectChanges();
    });

    it('should create', () => {
        expect(component).toBeTruthy();
    });

    it('should call fetchPersonnelList on page Oninit', fakeAsync(() => {
        component.ngOnInit();
        tick(1000);
        expect(service.fetchPersonnelList).toHaveBeenCalled();//error
        flush();
    }));
});

更新

根据forestG的建议,我通过注入服务来更新代码。当模拟服务存在时,我仍然收到错误消息:

Error: &lt;toHaveBeenCalled&gt; : Expected a spy, but got Function. 添加模拟服务后,为什么会出现此错误?

建议更新

我已经更新了我的代码,例如:

it('should call fetchPersonnelList on page Oninit', fakeAsync(() => {
        const fetchPersonnelListSpy = spyOn(
            service,
            'fetchPersonnelList'
        ).and.returnValue(of([]));
        component.ngOnInit();
        tick(1000);
        expect(fetchPersonnelListSpy).toHaveBeenCalled(); 
        flush();
    }));

有用。但是我的模拟服务有什么好处呢?我怎么能期待我的模拟数据。我可以将我的数据直接放在retunValue 部分吗?有人帮我吗?

【问题讨论】:

  • 服务未定义
  • @MWO - 你能检查我的 cmets 吗?

标签: angular angular-test


【解决方案1】:

您忘记获取对您的服务的引用:

   beforeEach(() => {
        fixture = TestBed.createComponent(ListPersonnelComponent);
        component = fixture.componentInstance;
        router = TestBed.inject(Router);
        service = TestBed.inject(PersonnelDataService);  // add this
        fixture.detectChanges();
    });

【讨论】:

  • 已经提供了还需要注入吗?在我进行更改后收到错误消息 `Error: <toHaveBeenCalled> : Expected a spy, but got Function.` 当我已经有了模拟服务时,为什么会出现此错误?
  • 试试,const fetchPersonnelListSpy = spyOn(service, 'fetchPersonnelList');期望(fetchPersonnelListSpy).toHaveBeenCalled();
  • @Mr.Stash,你能看看我的suggestion update 吗?
【解决方案2】:

您应该能够直接监视服务 spyOn(component.service, 'fetchPersonnelList') 并使用 .callThrough() 来调用模拟函数,如果您想阻止调用模拟函数并传递一些其他值,则使用 .returnValue(of([]));

it('should call fetchPersonnelList on page Oninit', () => {
  const fetchPersonnelListSpy = spyOn(component.service, 'fetchPersonnelList').and.callThrough();
  component.ngOnInit();
  expect(fetchPersonnelListSpy).toHaveBeenCalled();
});

【讨论】:

    猜你喜欢
    • 2018-04-29
    • 2022-12-08
    • 2022-12-21
    • 2022-12-24
    • 2022-12-25
    • 2023-01-21
    • 2023-02-06
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多