单元测试位置在async-await中的角度

单元测试位置在async-await中的角度

问题描述:

我将Angular 9+与业力测试运行程序和茉莉花测试框架一起用于单元测试.

I am using Angular 9+ with karma test runner and jasmine test framework for unit tests.

我只想对具有依赖项注入的 app组件 进行单元测试:

I wanted to unit test only app component which has a dependency injection:

app.component.ts

import { Component, EmbeddedViewRef } from '@angular/core';
import * as moment from 'moment-timezone';
import { OtherServiceService } from './other-service.service';
import { Location } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    constructor(private sampleService: OtherService, private location: Location){}

    async func(){
        await this.sampleService.func2().toPromise();
        console.log('Async call completed');
        this.location.go('/index.html');
    }
}

other-service.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class OtherServiceService {

  constructor(private http: HttpClient) { }

  func2(){
    return this.http.post('' , null);
  }
}

到目前为止我已经尝试过的单元测试:

The unit test i have tried so far:

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { AppComponent } from './app.component';
import { OtherServiceService } from './other-service.service';

const locationStub = {
  go: jasmine.createSpy('go')
}

describe('AppComponent', () => {
  let otherServiceStub;
  let fixture, component;
  beforeEach(async(() => {
    otherServiceStub = jasmine.createSpyObj(['func2']);

    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        {provide: OtherServiceService , useValue: otherServiceStub},
        {provide: Location, useValue: locationStub}
    ],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
  });

  it('should create the app', () => {
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it('should check for correct logs',fakeAsync(() => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    const location = fixture.debugElement.injector.get(Location);
    let spyObj = spyOn(console,'log');
    component.func();
    tick();
    expect(spyObj).toHaveBeenCalledWith('Async call completed');
    expect(location.go).toHaveBeenCalledWith('/index.html');
 }));


});

在运行ng test --code-coverage时,它始终显示错误 预期的间谍已被调用为:['/index.html'],但从未被调用..

On running ng test --code-coverage, it always shows error Expected spy go to have been called with: [ '/index.html' ] but it was never called..

在覆盖率报告中,该行显示为被覆盖(this.location.go),但是测试失败,我似乎无法理解为什么.我还从寻求帮助,但没有成功.

On the coverage report, it shows the line as covered (this.location.go) , but the test fails, and I can't seem to understand why. I have also taken help from this, but to no success.

UPDATE 1.0 :

UPDATE 1.0:

我已经尝试过@ AliF50的建议:

I have tried as suggested by @AliF50:

  async func(){
    await this.sampleService.func2().toPromise();
    console.log('Async call completed');
    this.location.go('/index.html');
    console.log('After location go in component');
  } 

  it('should check for correct logs',fakeAsync(() => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    let spyObj = spyOn(console,'log');
    component.func();
    tick();
    const location = fixture.debugElement.injector.get(Location);
    expect(spyObj).toHaveBeenCalledWith('Async call completed');
    console.log('Before location go in test');
    expect(location.go).toHaveBeenCalledWith('/index.html');
    console.log('After location go in test');
 }));

但是,令我惊讶的是,即使控制台显示有被覆盖的行,控制台日志中的都没有被打印.

But to my suprise none of the console logs are being printed, even though it shows lines as covered.

UPDATE 2.0 :

UPDATE 2.0:

如@ AliF50所建议:

As suggested by @AliF50:

  it('should check for correct logs',fakeAsync(() => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    let spyObj = spyOn(console,'log').and.callThrough();
    component.func();
    tick();
    const location = fixture.debugElement.injector.get(Location);
    expect(spyObj).toHaveBeenCalledWith('Async call completed');
    console.log('Before location go in test');
    expect(location.go).toHaveBeenCalledWith('/index.html');
    console.log('After location go in test');
 }));

所有控制台日志正在打印,但错误仍然存​​在.

All the console logs are being printed, but the error still remains.

UPDATE 3.0 :任何人都好运吗?这仍然是一个悬而未决的问题

UPDATE 4.0 :感谢安德烈(Andrei).问题已解决.

最后,经过了这么多时间,再加上 @Andrei 的贡献,我才能够提出以下问题的答案:

Finally after so much time, and @Andrei's contribution, I was able to come up with the answer to this question:

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { AppComponent } from './app.component';
import { OtherServiceService } from './other-service.service';
import { Location } from '@angular/common';

fdescribe('AppComponent', () => {
  let otherServiceStub;
  let fixture, component;
  beforeEach(async(() => {
    otherServiceStub = jasmine.createSpyObj(['func2']);

    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        {provide: OtherServiceService , useValue: otherServiceStub},
        Location
    ],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
  });

  it('should create the app', () => {
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it('should check for correct logs',async () => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    let locationObj = TestBed.inject(Location);
    let spyObj = spyOn(locationObj,'go');
    await component.func();
    expect(spyObj).toHaveBeenCalledWith('/index.html');
 });


});

单元测试正在通过,所有行均显示为已覆盖.

The Unit test is passing now with all the lines are being shown as covered.