我正在尝试运行一个简单的测试来检查是否已创建组件。
使用业力karma start ./test-config/karma.conf.js
运行测试时,得到以下输出:
10 10 2018 10:50:22.316:ERROR [HeadlessChrome 0.0.0 (Linux 0.0.0) | Create account component | should be created]: Error: StaticInjectorError(t)[t -> t]:
StaticInjectorError(Platform: core)[t -> t]:
NullInjectorError: No provider for t!
error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 't', Function ], ngDebugContext: t({ view: Object({ def: Object({ factory: Function, nodeFlags: 33603585, rootNodeFlags: 33554433, nodeMatchedQueries: 0, flags: 0, nodes: [ Object({ nodeIndex: 0, parent: null, renderParent: null, bindingIndex: 0, outputIndex: 0, checkIndex: 0, flags: 33554433, childFlags: 49152, directChildFlags: 49152, childMatchedQueries: 0, matchedQueries: Object({ }), matchedQueryIds: 0, references: Object({ }), ngContentIndex: null, childCount: 1, bindings: [ ], bindingFlags: 0, outputs: [ ], element: Object({ ns: '', name: 'page-create-account', attrs: [ ], template: null, componentProvider: Object({ nodeIndex: 1, parent: <circular reference: Object>, renderParent: <circular reference: Object>, bindingIndex: 0, outputIndex: 0, checkIndex: 1, flags: 49152, childFlags: 0, directChildFlags: 0, childMatchedQueries: 0, matchedQueries: Object, matchedQueryIds: 0, references: Object, ngContentIndex: -1, childCount: 0, ...
at t.get (http://localhost:9876/base/test-config/karma-test-shim.js?6323aa11dcffe596b12ee89cf9d5010482d220c9:45:142)
这是要测试的组件(我简化为隔离问题的最简单逻辑):
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {FormBuilder, FormGroup} from "@angular/forms";
import {UsernameValidator} from "../../validators/username";
@Component({
selector: 'page-create-account',
templateUrl: 'create-account.html',
})
export class CreateAccountPage {
userForm: FormGroup;
username;
email;
password;
constructor(public navCtrl: NavController,
public formBuilder: FormBuilder,
public usernameValidator: UsernameValidator){
this.userForm = this.formBuilder.group({});
}
}
这是测试:
import {async, TestBed} from '@angular/core/testing';
import {IonicModule, Nav, NavController} from 'ionic-angular';
import {
UsernameValidatorMock,
FormBuilderMock,
NavControllerMock,
NavMock
} from '../../../test-config/mocks-ionic';
import {CreateAccountPage} from "./create-account";
import {FormBuilder} from "@angular/forms";
import {UsernameValidator} from "../../validators/username";
import {UserService} from "../../services/user.service";
import {Observable} from "rxjs";
describe('Create account component', () => {
let fixture;
let component;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CreateAccountPage],
imports: [
IonicModule.forRoot(CreateAccountPage)
],
providers: [
{ provide: Nav, useClass: NavMock},
{ provide: NavController, useClass: NavControllerMock},
{ provide: FormBuilder, useClass: FormBuilderMock},
{ provide: UserService, useClass: UserServiceMock},
{ provide: UsernameValidator, useClass: UsernameValidatorMock },
]
})
}));
beforeEach(() => {
fixture = TestBed.createComponent(CreateAccountPage);
component = fixture.componentInstance;
});
it('should be created', () => {
expect(component instanceof CreateAccountPage).toBe(true);
});
});
这是原始的UsernameValidator:
import { Injectable } from '@angular/core';
import { FormControl } from '@angular/forms';
import {UserService} from '../services/user.service';
@Injectable()
export class UsernameValidator {
debouncer: any;
object_username: any = {};
constructor(public userService: UserService) {
}
checkUsername(control: FormControl): Promise<any> {
clearTimeout(this.debouncer);
return new Promise(resolve => {
this.debouncer = setTimeout(() => {
this.object_username = {username: control.value};
this.userService.validateUsername(this.object_username).subscribe((res) => {
console.log(res);
if ( res === true) {
resolve({'username taken': true});
}
}, (err) => {
resolve(null);
});
}, 1000);
});
}
}
似乎无法注入某些提供程序,但是我已经为所有使用的依赖项甚至第二级依赖项(例如UserProvider for UsernameValidator)创建了模拟程序。测试成功通过,没有注入UsernameValidator。知道为什么不能注入此类吗?
版本:
Ionic:
ionic (Ionic CLI) : 4.1.1
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.2.0
Cordova:
cordova (Cordova CLI) : 8.0.0
Cordova Platforms : android 6.4.0, ios 4.5.5
答案 0 :(得分:0)
我在没有自定义类的情况下运行了您的代码,并且效果很好。 过去,我在使用离子角3.9.2时遇到了Ionic cli 4的问题。
请再次使用ionic-cli 3.20.0进行检查:
[13:23:07]> (dev)$ionic info
cli packages: (E:\Usuarios\dceresa\AppData\Roaming\npm\node_modules)
@ionic/cli-utils : 1.19.2
ionic (Ionic CLI) : 3.20.0
global packages:
cordova (Cordova CLI) : 8.0.0
local packages:
@ionic/app-scripts : 3.1.5
Cordova Platforms : android 6.2.3 browser 5.0.3
Ionic Framework : ionic-angular 3.9.2-201807062122
以防万一您对我的.spec感到好奇:
import { async, TestBed } from '@angular/core/testing';
import { IonicModule, Nav, NavController } from 'ionic-angular';
import { CreateAccountPage } from "./create-account";
import { FormBuilder } from "@angular/forms";
import { Observable } from "rxjs";
import { NavControllerMock } from 'ionic-mocks';
fdescribe('Create account component', () => {
let fixture;
let component;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CreateAccountPage],
imports: [
IonicModule.forRoot(CreateAccountPage)
],
providers: [
{ provide: NavController, useClass: NavControllerMock },
FormBuilder
]
})
}));
beforeEach(() => {
fixture = TestBed.createComponent(CreateAccountPage);
component = fixture.componentInstance;
});
it('should be created', () => {
expect(component instanceof CreateAccountPage).toBe(true);
});
});
以及组件:
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { FormBuilder, FormGroup } from "@angular/forms";
@Component({
selector: 'page-create-account',
templateUrl: 'create-account.html',
})
export class CreateAccountPage {
userForm: FormGroup;
username;
email;
password;
constructor(public navCtrl: NavController,
public formBuilder: FormBuilder) {
this.userForm = this.formBuilder.group({});
}
}
答案 1 :(得分:0)
我终于发现了问题。 UserService
取决于HttpClient
,该提供程序未包含该模拟。这是必要的,因为UsernameValidatorMock
是UsernameValidator
的子类,因此必须注入原始类的所有依赖项。
我可以获得具体错误:
StaticInjectorError(Platform: core)[UserService -> HttpClient]:
NullInjectorError: No provider for HttpClient!
代替:
StaticInjectorError(Platform: core)[t -> t]:
NullInjectorError: No provider for t!
通过删除webpack
的4.2.0版本(因为业力已经取决于webpack
)并将ts-loader
从5.4.1降级到3.4.0。
尽管如此,我最终还是使用了一个验证器类的间谍,如下所示:
beforeEach(async(() => {
userValidatorUsernameSpy = jasmine.createSpyObj('UsernameValidator', ['checkUsername']);
TestBed.configureTestingModule({
declarations: [CreateAccountPage],
imports: [
FormsModule,
ReactiveFormsModule,
IonicModule.forRoot(CreateAccountPage)
],
providers: [
{provide: NavController, useValue: navControllerSpy},
{provide: NavParams, useFactory: () => NavParamsMock.instance()},
{provide: Platform, useFactory: () => PlatformMock.instance()},
{provide: UsernameValidator, useValue: usernameSpy},
]
}).compileComponents();
fixture = TestBed.createComponent(CreateAccountPage);
component = fixture.componentInstance;
}
));