我使用 Angular 9+ 与 karma 测试运行器和 jasmine 测试框架进行单元测试。
我只想进行单元测试app component
其中有一个依赖注入:
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);
}
}
到目前为止我尝试过的单元测试:
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 时,它总是显示错误Expected spy go to have been called with: [ '/index.html' ] but it was never called.
.
在覆盖率报告上,它显示该行已被覆盖 (this.location.go) ,但测试失败,我似乎无法理解为什么。我也得到了帮助this https://stackoverflow.com/questions/48202042/angular-how-to-test-a-component-which-requires-a-location,但没有成功。
UPDATE 1.0
:
我已经按照@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');
}));
但令我惊讶的是none of the console logs
正在打印,即使它显示的行已被覆盖。
UPDATE 2.0
:
正如@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
正在打印,但错误仍然存在。
UPDATE 3.0
:
有人运气好吗?这仍然是一个悬而未决的问题
UPDATE 4.0
:
感谢安德烈。问题现在解决了。