如何在 Angular 中测试 ngOnInit?

问题描述 投票:0回答:1
我正在使用 Angular 和 Jasmine。我为一个名为培训师的实体编写了一个编辑表单。我的 ngOnInit 函数从 url 中获取培训师 ID,然后进行服务调用以从数据库中获取培训师。我试图在测试中检查表单数据是否已通过检查一个字段(firstName)来预填充,但我不断收到错误:

Expected null to be 'Devin'.


当我console.log trainerForm.value时,它是空的:

LOG: Object{firstName: null, lastName: null, email: '', officeLocation: '', pathwaysControl: [], courses: [], skills: null}


这是我的 TS 文件:

export class EditTrainerComponent implements OnInit { userId: number | undefined; currentPage: string = ''; targetElementWidth: number = 0; offices: OfficeLocation[] = []; allCourses: Course[] = []; courses: Course[] = []; pathways: Pathway[] = []; prevPathways: string[] = []; // remove me? skills: Skill[] = []; trainerForm!: FormGroup; trainer: Trainer = emptyTrainer(); experienceExpand: string = 'out'; showModal: boolean = false; constructor( private formBuilder: FormBuilder, private trainerService: TrainerService, private officeLocationService: OfficeLocationService, private courseService: CourseService, private pathwayService: PathwayService, private route: ActivatedRoute, private router: Router, private dialog: MatDialog, private location: Location ) { this.trainerForm = this.formBuilder.group({ firstName: [ null, [ Validators.required, Validators.minLength(2), Validators.maxLength(12), this.noBlankSpacesValidator, ], ], lastName: [ null, [ Validators.required, Validators.minLength(2), Validators.maxLength(12), this.noBlankSpacesValidator, ], ], email: [ '', [ Validators.required, Validators.pattern( '^[a-zA-Z0-9._%+-]+@(?:[a-zA-Z0-9-]+.)?fdmgroup.com$' ), ], [this.emailExistsValidator()], ], officeLocation: ['', Validators.required], pathwaysControl: [[]], courses: [[]], skills: [null, Validators.required], }); } ngOnInit(): void { this.trainerService.getAllSkills().subscribe((skills) => { this.skills = skills; }); this.officeLocationService.getAllOfficeLocations().subscribe((offices) => { this.offices = offices; }); this.courseService.getAllCourses().subscribe((courses) => { this.courses = courses; this.allCourses = courses; }); this.pathwayService.getAllPathways().subscribe((pathways) => { this.pathways = pathways; // Fetch the trainer that is being edited and populate fields // This is inside getAllPathways because the ability to load pathways requires // this.pathways to be loaded first const trainerId = this.getTrainerId(); this.trainerService.getTrainerById(trainerId).subscribe((trainer) => { this.trainer = trainer; this.trainerForm.patchValue({ firstName: this.trainer.firstName, lastName: this.trainer.lastName, email: this.trainer.email, officeLocation: this.trainer.officeLocation?.city, pathwaysControl: this.getPathwaysByCourses( this.trainer.coursesEligibleToTeach ), courses: this.getCourseNames(this.trainer.coursesEligibleToTeach), skills: this.getSkillNames(this.trainer.skills), }); }); }); }
这是我的测试文件:

describe('EditTrainerComponent', () => { let component: EditTrainerComponent; let fixture: ComponentFixture<EditTrainerComponent>; let mockTrainerService: jasmine.SpyObj<TrainerService>; let mockCourseService: jasmine.SpyObj<CourseService>; let mockPathwayService: jasmine.SpyObj<PathwayService>; let locationSpy: SpyLocation; let mockTrainer: Trainer; let mockSkills: Skill[] = []; let mockPathways: Pathway[] = []; let mockCourses: Course[] = []; beforeEach(async () => { mockTrainer = { userId: 14, firstName: "Devin", lastName: "Troy", email: "[email protected]", username: "devin.troy", userType: { userTypeId: 2, name: "Trainer" }, officeLocation: { id: 5, city: "Charlotte", stateOrProvince: "NC", country: { countryId: 2, countryName: "United States", region: { id: 1, regionName: "North America", regionCode: "NA" }, countryCode: "USA" } }, dateJoined: new Date("2020-08-12T00:22:10.000+00:00"), bio: "", trainerStatus: "active", trainerRoles: [], coursesEligibleToTeach: [], skills: [ { id: 22, name: "Excel" }, { id: 5, name: "APM" } ], dateModified: new Date("2026-01-01T00:00:00.000+00:00") }; mockSkills = [...] mockPathways = [...] mockCourses = [...] mockTrainerService = jasmine.createSpyObj('TrainerService', [ 'checkIfEmailExists', 'getAllSkills', 'getTrainerById' ]); mockCourseService = jasmine.createSpyObj('CourseService', [ 'getCoursesByPathwayId', ]); mockPathwayService = jasmine.createSpyObj('PathwayService', [ 'getAllPathways', ]); mockCourseService.getCoursesByPathwayId.and.returnValue(of(mockCourses)); mockTrainerService.getAllSkills.and.returnValue(of(mockSkills)); mockTrainerService.checkIfEmailExists.and.returnValue(of(false)); mockPathwayService.getAllPathways.and.returnValue(of(mockPathways)) mockTrainerService.getTrainerById.and.returnValue(of(mockTrainer)); await TestBed.configureTestingModule({ declarations: [EditTrainerComponent], imports: [ ReactiveFormsModule, HttpClientTestingModule, RouterModule.forRoot([]), MatFormFieldModule, MatInputModule, MatSelectModule, NoopAnimationsModule, ], providers: [ { provide: TrainerService, useValue: mockTrainerService }, { provide: Location, useClass: SpyLocation }, ], }).compileComponents(); locationSpy = TestBed.inject(Location) as SpyLocation; fixture = TestBed.createComponent(EditTrainerComponent); component = fixture.componentInstance; component.trainer = mockTrainer; component.pathways = mockPathways; component.courses = mockPathways[0].courses; fixture.detectChanges(); }); // HERE IS MY TEST THAT IS FAILING: fit('should show values for existing trainer', async() => { mockTrainerService.getTrainerById.and.returnValue(of(mockTrainer)); fixture.detectChanges(); await fixture.whenStable(); expect(component.trainerForm).toBeDefined(); // passes expect(component.trainerForm.controls['firstName']).toBeTruthy(); // passes expect(component.pathways).toEqual(mockPathways); // passes console.log(component.trainerForm.value) // logs obj with null values expect(component.trainerForm.get('firstName')?.value).toBe(mockTrainer.firstName); // FAILS });
    
angular unit-testing testing rxjs jasmine
1个回答
0
投票
您可以使用角度测试中的

fakeAsync

flush
 来等待异步操作完成。

您必须在测试用例中调用

ngOnInit

 才能设置值。

您可以删除

fixture.detectChanges()

 并手动触发 
ngOnInit
 方法。

it('should show values for existing trainer', fakeAsync(() => { mockPathwayService.getAllPathways.and.returnValue(of(mockPathways)); mockTrainerService.getTrainerById.and.returnValue(of(mockTrainer)); component.ngOnInit(); flush(); expect(component.trainerForm).toBeDefined(); // passes expect(component.trainerForm.controls['firstName']).toBeTruthy(); // passes expect(component.pathways).toEqual(mockPathways); // passes console.log(component.trainerForm.value); // logs obj with null values expect(component.trainerForm.get('firstName')?.value).toBe( mockTrainer.firstName ); // FAILS }));
完整代码:

import { TestBed, ComponentFixture, waitForAsync, fakeAsync, flush, } from '@angular/core/testing'; import { AppComponent, PathwayService, TrainerService } from './app.component'; import { AppModule } from './app.module'; import { SpyLocation } from '@angular/common/testing'; import { of } from 'rxjs'; describe('EditTrainerComponent', () => { let component: AppComponent; let fixture: ComponentFixture<AppComponent>; let mockPathwayService: jasmine.SpyObj<PathwayService> = jasmine.createSpyObj( 'PathwayService', ['getAllPathways'] ); let mockTrainerService: jasmine.SpyObj<TrainerService> = jasmine.createSpyObj( 'TrainerService', ['getTrainerById'] ); let locationSpy: SpyLocation; let mockTrainer: any = { userId: 14, firstName: 'Devin', lastName: 'Troy', email: '[email protected]', username: 'devin.troy', userType: { userTypeId: 2, name: 'Trainer', }, officeLocation: { id: 5, city: 'Charlotte', stateOrProvince: 'NC', country: { countryId: 2, countryName: 'United States', region: { id: 1, regionName: 'North America', regionCode: 'NA', }, countryCode: 'USA', }, }, dateJoined: new Date('2020-08-12T00:22:10.000+00:00'), bio: '', trainerStatus: 'active', trainerRoles: [], coursesEligibleToTeach: [], skills: [ { id: 22, name: 'Excel', }, { id: 5, name: 'APM', }, ], dateModified: new Date('2026-01-01T00:00:00.000+00:00'), }; let mockSkills: any[] = []; let mockPathways: any[] = []; let mockCourses: any[] = []; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [AppComponent], imports: [], providers: [ { provide: TrainerService, useValue: mockTrainerService }, { provide: PathwayService, useValue: mockPathwayService }, { provide: Location, useClass: SpyLocation }, ], }).compileComponents(); // locationSpy = TestBed.inject(Location) as SpyLocation; fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; }); // HERE IS MY TEST THAT IS FAILING: it('should show values for existing trainer', fakeAsync(() => { mockPathwayService.getAllPathways.and.returnValue(of(mockPathways)); mockTrainerService.getTrainerById.and.returnValue(of(mockTrainer)); component.ngOnInit(); flush(); expect(component.trainerForm).toBeDefined(); // passes expect(component.trainerForm.controls['firstName']).toBeTruthy(); // passes expect(component.pathways).toEqual(mockPathways); // passes console.log(component.trainerForm.value); // logs obj with null values expect(component.trainerForm.get('firstName')?.value).toBe( mockTrainer.firstName ); // FAILS })); });
    
© www.soinside.com 2019 - 2024. All rights reserved.