我正在使用 Jasmine 测试我的角度代码。我已经导入了所有内容,但仍然出现错误。这是两个错误:
NullInjectorError:R3InjectorError(DynamicTestModule)[FormBuilder -> FormBuilder]:NullInjectorError:没有 FormBuilder 的提供程序!
期望未定义为真。
这些错误出现在多个组件上。我附上了一个存在这些错误的组件的示例。我该如何解决它? (我是初学者所以请尽量用最简单的方式回答)
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {FormsModule } from '@angular/forms';
import { SortPipe } from './sort.pipe';
import { CustomPipeComponent } from './custom-pipe/custom-pipe.component';
import { CustpipeComponent } from './custpipe/custpipe.component';
import { RideFilterPipePipe } from './ride-filter-pipe.pipe';
import { ReactFormComponent } from './react-form/react-form.component';
import { TemplateDrivenFormComponent } from './template-driven-form/template-driven-form.component';
import { EmailValidator } from './template-driven-form/emailValidator';
@NgModule({
declarations: [
AppComponent,
SortPipe,
CustomPipeComponent,
CustpipeComponent,
RideFilterPipePipe,
ReactFormComponent,
TemplateDrivenFormComponent,
EmailValidator
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.spec.ts
import { TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule,
ReactiveFormsModule
],
declarations: [
AppComponent
],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'carpool'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('carpool');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('carpool app is running!');
});
});
reactFormComponent.html
<div class="login-comp">
<div class="container">
<div class="outer-box">
<h3 class="title">Reactive form</h3>
<form [formGroup]="registerForm">
<div class="form-group">
<label class="">Name</label>
<input class=" form-control" type="text" formControlName="firstName">
<p *ngIf="(registerForm.get('firstName')?.dirty ||
registerForm.get('firstName')?.touched ) &&
registerForm.get('firstName')?.errors "
class="alert alert-danger">This is required</p>
</div>
<div class="form-group">
<label class="">email</label>
<input class=" form-control" type="email" formControlName="email">
<p *ngIf="(registerForm.get('email')?.dirty ||
registerForm.get('email')?.touched ) &&
registerForm.get('email')?.errors "
class="alert alert-danger">invalid</p>
</div>
<div class="form-group">
<fieldset formGroupName="address">
<label class="">Steet</label>
<input class=" form-control" type="text" formControlName="street">
<label class="">Zip</label>
<input class=" form-control" type="text" formControlName="zip">
<label class="">City</label>
<input class=" form-control" type="text" formControlName="city">
</fieldset>
</div>
<button type="submit" [disabled]="!registerForm.valid" class="btn btn-primary" (click)="subForm()">Submit</button>
</form>
<div [hidden]="!submittedForm">
<p>Name: {{registerForm.get('firstName')?.value}}</p>
<p>Name: {{registerForm.get('email')?.value}}</p>
<p>Street: {{registerForm.get('address.street')?.value}}</p>
<p>City: {{registerForm.get('address.city')!.value}}</p>
<p>zip: {{registerForm.get('address.zip')!.value}}</p>
</div>
</div>
</div>
</div>
reactFormComponent.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-react-form',
templateUrl: './react-form.component.html',
styleUrls: ['./react-form.component.css']
})
export class ReactFormComponent implements OnInit {
registerForm!:FormGroup;
submittedForm!:boolean;
constructor(private formBuilder:FormBuilder) {}
ngOnInit(): void {
this.registerForm=this.formBuilder.group({
firstName: ['',Validators.required],
email: ['', validateEmail],
address: this.formBuilder.group({
street:[],
zip:[],
city:['',Validators.required]
})
});
}
subForm() {
this.submittedForm=true;
console.log(this.registerForm);
}
}
function validateEmail(eid:FormControl):any {
let email_regex=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return email_regex.test(eid.value)?null : {
emailInvalid: {
message: 'Invalid Format'
}
};
}```
该错误表示在
app.component.spec.ts
中创建的测试模块找不到 FormBuilder
的提供程序。
FormBuilder
定义在 FormsModule
中。您会注意到它被导入到 AppModule
中(这就是您的应用程序编译和运行的原因),但它没有被导入到 configureTestingModule
中的 app.component.spec.ts
中。
修复:
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule,
FormsModule, // << ----- add this line
ReactiveFormsModule
],
不是在
app.component.spec.ts
中,而是在 <your-component-name>.spec.ts
中,你必须添加这些:
imports: [
FormsModule,
ReactiveFormsModule,
],
providers: [<your-providers>],
declarations: [<your-component-name>],
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule,
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule,
FormsModule, // << ----- add this line
ReactiveFormsModule // You should add this too
],
这将解决测试中以下代码的问题...
imports: [
FormsModule,
ReactiveFormsModule,
],
providers: [FormBuilder],
但是之后我也遇到了不同的错误
Error: NG0204: Can't resolve all parameters for FormGroup: (?, ?, ?).
提到this,我后来选择将其包含在我的“tsconfig.spec.json”文件中。我正在使用 Angular 14。看来我需要重构应用程序代码本身,但现在我选择不这样做,而是在测试 tsconfig 文件中设置它。
"extends": "./tsconfig.json",
"compilerOptions": {
"useDefineForClassFields": false
},
发布这两个单独的解决方案,因为有些人也可能会遇到这些错误链...希望这有帮助!