最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - NullInjectorError: R3InjectorError(DynamicTestModule)[FormBuilder -> FormBuilder]: NullInjectorError: No pro

programmeradmin3浏览0评论

I am testing my angular code using Jasmine. I have imported everything but still getting errors. These are the 2 errors:

NullInjectorError: R3InjectorError(DynamicTestModule)[FormBuilder -> FormBuilder]: NullInjectorError: No provider for FormBuilder!

Expected undefined to be truthy.

These errors are on multiple ponent. I have attached example of one ponent with these errors. How can I solve it ? (I am a beginner so please try to answer it in the simplest manner)

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 './appponent';

import {FormsModule } from '@angular/forms';
import { SortPipe } from './sort.pipe';
import { CustomPipeComponent } from './custom-pipe/custom-pipeponent';
import { CustpipeComponent } from './custpipe/custpipeponent';
import { RideFilterPipePipe } from './ride-filter-pipe.pipe';
import { ReactFormComponent } from './react-form/react-formponent';
import { TemplateDrivenFormComponent } from './template-driven-form/template-driven-formponent';
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 { }

appponent.spec.ts

import { TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './appponent';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        ReactiveFormsModule
      ],
      declarations: [
        AppComponent
      ],
    })pileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixtureponentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'carpool'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixtureponentInstance;
    expect(app.title).toEqual('carpool');
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const piled = fixture.nativeElement as HTMLElement;
    expect(piled.querySelector('.content span')?.textContent).toContain('carpool app is running!');
  });
});

reactFormComponent.html

<div class="login-p">
    <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-formponent.html',
  styleUrls: ['./react-formponent.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'
    }
  };
}```

I am testing my angular code using Jasmine. I have imported everything but still getting errors. These are the 2 errors:

NullInjectorError: R3InjectorError(DynamicTestModule)[FormBuilder -> FormBuilder]: NullInjectorError: No provider for FormBuilder!

Expected undefined to be truthy.

These errors are on multiple ponent. I have attached example of one ponent with these errors. How can I solve it ? (I am a beginner so please try to answer it in the simplest manner)

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.ponent';

import {FormsModule } from '@angular/forms';
import { SortPipe } from './sort.pipe';
import { CustomPipeComponent } from './custom-pipe/custom-pipe.ponent';
import { CustpipeComponent } from './custpipe/custpipe.ponent';
import { RideFilterPipePipe } from './ride-filter-pipe.pipe';
import { ReactFormComponent } from './react-form/react-form.ponent';
import { TemplateDrivenFormComponent } from './template-driven-form/template-driven-form.ponent';
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.ponent.spec.ts

import { TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.ponent';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        ReactiveFormsModule
      ],
      declarations: [
        AppComponent
      ],
    }).pileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.ponentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'carpool'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.ponentInstance;
    expect(app.title).toEqual('carpool');
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const piled = fixture.nativeElement as HTMLElement;
    expect(piled.querySelector('.content span')?.textContent).toContain('carpool app is running!');
  });
});

reactFormComponent.html

<div class="login-p">
    <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.ponent.html',
  styleUrls: ['./react-form.ponent.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'
    }
  };
}```
Share Improve this question edited Feb 17, 2022 at 8:02 Anurag Srivastava 14.4k4 gold badges36 silver badges45 bronze badges asked Feb 17, 2022 at 4:42 muskaan sharmamuskaan sharma 1772 gold badges5 silver badges12 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 3

The error indicates the test module created in app.ponent.spec.ts cannot find the provider for FormBuilder.

FormBuilder is defined in the FormsModule. You will notice that it is imported in AppModule (which is why your app piles and runs) but it is not imported in configureTestingModule in app.ponent.spec.ts.

Fix:

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        FormsModule,               // << ----- add this line
        ReactiveFormsModule
      ],

Not in the app.ponent.spec.ts, but in <your-ponent-name>.spec.ts you've got to add those:

        imports: [
            FormsModule,
            ReactiveFormsModule,
        ],
        providers: [<your-providers>],
        declarations: [<your-ponent-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
      ],
        

This will solve the issue with below code in test...

 imports: [
   FormsModule,
   ReactiveFormsModule,
 ],
 providers: [FormBuilder],

But after that I also got different error

 Error: NG0204: Can't resolve all parameters for FormGroup: (?, ?, ?).

Referring to this, I have later on opted to include this in my "tsconfig.spec.json" file. I am using Angular 14. It appear I need to refactor the application code itself, but for now I choose to not do it and set this in test tsconfig file instead.

"extends": "./tsconfig.json",
"pilerOptions": {    
  "useDefineForClassFields": false
},

Posting these 2 separate solution as some might encounter these chain of error too... hope this help!

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论