简体   繁体   English

Angular 8 Jasmine 和业力测试:模拟的 ngonit promise 值未在 DOM 中呈现

[英]Angular 8 Jasmine and karma testing: mocked ngonit promise value is not rendered in the DOM

My mock data in a test will not display in the markup when running the test.运行测试时,我在测试中的模拟数据不会显示在标记中。 No matter what i try (fakeasync, done, stubs) the content of the promise is not rendered in the markup after running the test.无论我尝试什么(fakeasync、done、stubs),运行测试后 promise 的内容都不会呈现在标记中。

Can anyone please tell me why this mocked promise data will not display in the dom.谁能告诉我为什么这个模拟的 promise 数据不会显示在 dom 中。 I have spent 2 days almost on this and it simply does not work no matter what i try.我几乎花了 2 天时间,无论我尝试什么,它都无法正常工作。 I'm using angular 8 and starting to think it's a bug in the framework.我正在使用 angular 8 并开始认为这是框架中的错误。

I have the following markup:我有以下标记:

<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>

This is the class:这是 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);
  }
}

This is the test:这是测试:

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];
  }
});

This worked for me这对我有用

proof:-证明:-

在此处输入图像描述

Also tried running single test case to show you that test centers are displaying now:-还尝试运行单个测试用例来向您展示测试中心现在正在显示:-

在此处输入图像描述

@Aakash Garg Ive accepted your answer as you got it right. @Aakash Garg Ive 接受了您的回答,因为您做对了。

After spending (yet) more time on this I found that the fact we created spies differently didn't make any difference.在花了(还)更多时间之后,我发现我们以不同方式创建间谍的事实并没有任何区别。

The key fact was you turned around fixture.detectChanges();关键事实是你转过身来 fixture.detectChanges(); await fixture.whenStable();等待fixture.whenStable(); I had them the other way around.我有他们相反的方式。

Also you added a fixture.detectChanges() in the test itself which was also necessary.您还在测试本身中添加了一个fixture.detectChanges(),这也是必要的。 The additonal whenStable call didn't seem to make any difference.附加的 whenStable 调用似乎没有任何区别。

In the end I used fixture.autoDetectChanges() which made it work without the fixture.whenStable call as below:最后我使用了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);
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM