Angular 8 Jasmine 和业力测试:mocked ngonit promise 值未在 DOM 中呈现
Angular 8 Jasmine and karma testing: mocked ngonit promise value is not rendered in the DOM
我在测试中的模拟数据在 运行 测试时不会显示在标记中。无论我尝试什么(fakeasync、完成、存根),承诺的内容都不会在 运行 测试后在标记中呈现。
谁能告诉我为什么这个模拟的 promise 数据不会显示在 dom 中。我几乎在这上面花了 2 天时间,但无论我尝试什么,它都不起作用。我正在使用 angular 8 并开始认为这是框架中的错误。
我有以下标记:
<div>
<div class="pt-8">
<!-- Displays -->
<ul>
<li *ngFor="let worker of workers">{{worker.getName()}}</li>
</ul>
<!-- DOES NOT DISPLAY -->
<ol>
<li *ngFor="let centre of centres">{{centre.name}}</li>
</ol>
</div>
</div>
这是class:
import { Component, OnInit, Input, Inject } from '@angular/core';
import { WorkcentersService } from 'app/services/workcenters.service';
import { Workcenter } from 'app/model/workcenter';
import { User } from 'app/model/user';
@Component({
selector: 'test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
workers: User[];
centres: Workcenter[];
constructor(private workcentersService: WorkcentersService) { }
ngOnInit(): void {
let user1 = new User(); user1.name = "worker 1"; user1.surname = "surname1";
let user2 = new User(); user2.name = "worker 2"; user2.surname = "surname2";
let user3 = new User(); user3.name = "worker 3"; user3.surname = "surname3";
this.workers = [user1, user2, user3];
this.workcentersService.getWorkcentersList().then(wc => this.centres = wc);
}
}
这是测试:
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { WorkcentersService } from 'app/services/workcenters.service';
import { Workcenter } from 'app/model/workcenter';
import { TestComponent } from './test.component';
fdescribe('TestComponent', () => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
beforeEach(async () => {
const mockCentres = createMockCentres();
const mockWorkcentersService = jasmine.createSpyObj(["getWorkcentersList"]);
mockWorkcentersService.getWorkcentersList.and.returnValue(Promise.resolve(mockCentres));
TestBed.configureTestingModule({
declarations: [TestComponent],
imports: [],
providers: [
{ provide: WorkcentersService, useValue: mockWorkcentersService }
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
await fixture.whenStable();
fixture.detectChanges();
});
// Passes
it('should create', () => {
expect(component).toBeTruthy();
});
// Passes
it('should render users', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll("ul li");
expect(displayedUsers.length).toEqual(3);
});
// Fails
it('should render centres', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll("ol li");
expect(displayedUsers.length).toEqual(2);
});
// Fails
it('should display "hello"', fakeAsync(() => {
fixture.detectChanges();
tick();
const displayedUsers = fixture.nativeElement.querySelectorAll("ol li");
expect(displayedUsers.length).toEqual(2);
}));
function createMockCentres(): Workcenter[] {
const mockCentre1 = new Workcenter();mockCentre1.id = 1;mockCentre1.name = "Test centre 1";
const mockCentre2 = new Workcenter();mockCentre2.id = 2;mockCentre2.name = "Test centre 2";
return [mockCentre1, mockCentre2];
}
});
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { WorkCenter } from './workCenter';
import { WorkcentersService } from './workcenters.service';
fdescribe('TestComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let mockWorkcentersService: WorkcentersService;
beforeEach(async () => {
const mockCentres = createMockCentres();
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [],
providers: [
WorkcentersService
]
});
fixture = TestBed.createComponent(AppComponent);
mockWorkcentersService = TestBed.get(WorkcentersService);
spyOn(mockWorkcentersService, 'getWorkcentersList').and.returnValue(new Promise((resolve, reject) => resolve(mockCentres)));
component = fixture.componentInstance;
await fixture.whenStable();
fixture.detectChanges();
});
// Passes
it('should create', () => {
expect(component).toBeTruthy();
});
// Passes
it('should render users', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll('ul li');
expect(displayedUsers.length).toEqual(3);
});
// Fails
it('should render centres', async () => {
expect(mockWorkcentersService.getWorkcentersList).toHaveBeenCalled();
fixture.detectChanges();
await fixture.whenStable();
const displayedUsers = fixture.nativeElement.querySelectorAll('ol li');
expect(displayedUsers.length).toEqual(2);
});
// Fails
it('should display "hello"', fakeAsync(() => {
fixture.detectChanges();
tick();
const displayedUsers = fixture.nativeElement.querySelectorAll('ol li');
expect(displayedUsers.length).toEqual(2);
}));
function createMockCentres(): WorkCenter[] {
const mockCentre1 = new WorkCenter(); mockCentre1.id = 1; mockCentre1.name = 'Test centre 1';
const mockCentre2 = new WorkCenter(); mockCentre2.id = 2; mockCentre2.name = 'Test centre 2';
return [mockCentre1, mockCentre2];
}
});
这对我有用
证明:-
还尝试了 运行 单个测试用例来向您展示测试中心现在正在显示:-
@Aakash Garg 我接受了你的回答,因为你答对了。
在这方面花费(还)更多时间后,我发现我们以不同方式创建间谍这一事实并没有产生任何影响。
关键事实是你转身
fixture.detectChanges();
等待 fixture.whenStable();
我把它们反过来了。
您还在测试本身中添加了一个 fixture.detectChanges() ,这也是必要的。附加的 whenStable 调用似乎没有任何区别。
最后我使用了 fixture.autoDetectChanges() 使得它在没有 fixture.whenStable 调用的情况下工作,如下所示:
beforeEach(async () => {
const mockCentres = createMockCentres();
const workers = { workers: createMockWorkers(), companyId: 22 };
const mockWorkcentersService = jasmine.createSpyObj(["getWorkcentersList"]);
mockWorkcentersService.getWorkcentersList.and.returnValue(Promise.resolve(mockCentres));
TestBed.configureTestingModule({
declarations: [CentreAssociateComponent],
imports: [],
providers: [
//WorkcentersService,
{ provide: WorkcentersService, useValue: mockWorkcentersService },
{ provide: MAT_DIALOG_DATA, useValue: workers },
{ provide: MatDialogRef, useValue: {} }
]
});
fixture = TestBed.createComponent(CentreAssociateComponent);
fixture.autoDetectChanges();
component = fixture.componentInstance;
await fixture.whenStable();
});
it('should render centres', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll("ol li");
expect(displayedUsers.length).toEqual(2);
});
我在测试中的模拟数据在 运行 测试时不会显示在标记中。无论我尝试什么(fakeasync、完成、存根),承诺的内容都不会在 运行 测试后在标记中呈现。
谁能告诉我为什么这个模拟的 promise 数据不会显示在 dom 中。我几乎在这上面花了 2 天时间,但无论我尝试什么,它都不起作用。我正在使用 angular 8 并开始认为这是框架中的错误。
我有以下标记:
<div>
<div class="pt-8">
<!-- Displays -->
<ul>
<li *ngFor="let worker of workers">{{worker.getName()}}</li>
</ul>
<!-- DOES NOT DISPLAY -->
<ol>
<li *ngFor="let centre of centres">{{centre.name}}</li>
</ol>
</div>
</div>
这是class:
import { Component, OnInit, Input, Inject } from '@angular/core';
import { WorkcentersService } from 'app/services/workcenters.service';
import { Workcenter } from 'app/model/workcenter';
import { User } from 'app/model/user';
@Component({
selector: 'test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
workers: User[];
centres: Workcenter[];
constructor(private workcentersService: WorkcentersService) { }
ngOnInit(): void {
let user1 = new User(); user1.name = "worker 1"; user1.surname = "surname1";
let user2 = new User(); user2.name = "worker 2"; user2.surname = "surname2";
let user3 = new User(); user3.name = "worker 3"; user3.surname = "surname3";
this.workers = [user1, user2, user3];
this.workcentersService.getWorkcentersList().then(wc => this.centres = wc);
}
}
这是测试:
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { WorkcentersService } from 'app/services/workcenters.service';
import { Workcenter } from 'app/model/workcenter';
import { TestComponent } from './test.component';
fdescribe('TestComponent', () => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
beforeEach(async () => {
const mockCentres = createMockCentres();
const mockWorkcentersService = jasmine.createSpyObj(["getWorkcentersList"]);
mockWorkcentersService.getWorkcentersList.and.returnValue(Promise.resolve(mockCentres));
TestBed.configureTestingModule({
declarations: [TestComponent],
imports: [],
providers: [
{ provide: WorkcentersService, useValue: mockWorkcentersService }
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
await fixture.whenStable();
fixture.detectChanges();
});
// Passes
it('should create', () => {
expect(component).toBeTruthy();
});
// Passes
it('should render users', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll("ul li");
expect(displayedUsers.length).toEqual(3);
});
// Fails
it('should render centres', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll("ol li");
expect(displayedUsers.length).toEqual(2);
});
// Fails
it('should display "hello"', fakeAsync(() => {
fixture.detectChanges();
tick();
const displayedUsers = fixture.nativeElement.querySelectorAll("ol li");
expect(displayedUsers.length).toEqual(2);
}));
function createMockCentres(): Workcenter[] {
const mockCentre1 = new Workcenter();mockCentre1.id = 1;mockCentre1.name = "Test centre 1";
const mockCentre2 = new Workcenter();mockCentre2.id = 2;mockCentre2.name = "Test centre 2";
return [mockCentre1, mockCentre2];
}
});
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { WorkCenter } from './workCenter';
import { WorkcentersService } from './workcenters.service';
fdescribe('TestComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let mockWorkcentersService: WorkcentersService;
beforeEach(async () => {
const mockCentres = createMockCentres();
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [],
providers: [
WorkcentersService
]
});
fixture = TestBed.createComponent(AppComponent);
mockWorkcentersService = TestBed.get(WorkcentersService);
spyOn(mockWorkcentersService, 'getWorkcentersList').and.returnValue(new Promise((resolve, reject) => resolve(mockCentres)));
component = fixture.componentInstance;
await fixture.whenStable();
fixture.detectChanges();
});
// Passes
it('should create', () => {
expect(component).toBeTruthy();
});
// Passes
it('should render users', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll('ul li');
expect(displayedUsers.length).toEqual(3);
});
// Fails
it('should render centres', async () => {
expect(mockWorkcentersService.getWorkcentersList).toHaveBeenCalled();
fixture.detectChanges();
await fixture.whenStable();
const displayedUsers = fixture.nativeElement.querySelectorAll('ol li');
expect(displayedUsers.length).toEqual(2);
});
// Fails
it('should display "hello"', fakeAsync(() => {
fixture.detectChanges();
tick();
const displayedUsers = fixture.nativeElement.querySelectorAll('ol li');
expect(displayedUsers.length).toEqual(2);
}));
function createMockCentres(): WorkCenter[] {
const mockCentre1 = new WorkCenter(); mockCentre1.id = 1; mockCentre1.name = 'Test centre 1';
const mockCentre2 = new WorkCenter(); mockCentre2.id = 2; mockCentre2.name = 'Test centre 2';
return [mockCentre1, mockCentre2];
}
});
这对我有用
证明:-
还尝试了 运行 单个测试用例来向您展示测试中心现在正在显示:-
@Aakash Garg 我接受了你的回答,因为你答对了。
在这方面花费(还)更多时间后,我发现我们以不同方式创建间谍这一事实并没有产生任何影响。
关键事实是你转身 fixture.detectChanges(); 等待 fixture.whenStable(); 我把它们反过来了。
您还在测试本身中添加了一个 fixture.detectChanges() ,这也是必要的。附加的 whenStable 调用似乎没有任何区别。
最后我使用了 fixture.autoDetectChanges() 使得它在没有 fixture.whenStable 调用的情况下工作,如下所示:
beforeEach(async () => {
const mockCentres = createMockCentres();
const workers = { workers: createMockWorkers(), companyId: 22 };
const mockWorkcentersService = jasmine.createSpyObj(["getWorkcentersList"]);
mockWorkcentersService.getWorkcentersList.and.returnValue(Promise.resolve(mockCentres));
TestBed.configureTestingModule({
declarations: [CentreAssociateComponent],
imports: [],
providers: [
//WorkcentersService,
{ provide: WorkcentersService, useValue: mockWorkcentersService },
{ provide: MAT_DIALOG_DATA, useValue: workers },
{ provide: MatDialogRef, useValue: {} }
]
});
fixture = TestBed.createComponent(CentreAssociateComponent);
fixture.autoDetectChanges();
component = fixture.componentInstance;
await fixture.whenStable();
});
it('should render centres', async () => {
const displayedUsers = fixture.nativeElement.querySelectorAll("ol li");
expect(displayedUsers.length).toEqual(2);
});