【问题标题】:NullInjectorError while testing测试时出现 NullInjectorError
【发布时间】:2021-09-21 21:32:05
【问题描述】:

在 Angular 12 中运行 ng test 时遇到以下问题:

NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]:NullInjectorError:没有 BaseURL 的提供者!错误 属性:对象({ ngTempTokenPath:空,ngTokenPath:['BaseURL', 'BaseURL' ] }) NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]:
NullInjectorError:没有 BaseURL 的提供者! 在 NullInjector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11101:1 ) 在 R3Injector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11268:1 ) 在 R3Injector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11268:1 ) 在 NgModuleRef$1.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:25332: 1) 在 Object.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:25046:1 ) 在lookupTokenUsingModuleInjector (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3342:1) 在 getOrCreateInjectable (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3454:1) 在 ɵɵdirectiveInject (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:14737:1) 在 NodeInjectorFactory.MenuComponent_Factory [作为工厂] (ng:///MenuComponent/ɵfac.js:5:7) 在 getNodeInjectable (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3549:1)

错误:预期未定义是真实的。 在 在用户上下文。 (http://localhost:9876/karma_webpack/webpack:/src/app/menu/menu.component.spec.ts:46:23) 在 ZoneDelegate.invoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:372:1) 在 ProxyZoneSpec.onInvoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:287:1)

spec.ts 的代码是:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuComponent } from './menu.component';
import { DishService } from '../services/dish.service';

describe('MenuComponent', () => {
  let component: MenuComponent;
  let fixture: ComponentFixture<MenuComponent>;

const mockDishService = {
  getDishes: () => {
     return {
        id: '000',
        name: 'nnnnn'
     }
  }
}

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [],
      declarations: [ MenuComponent ],
      providers: [
        { provide: DishService, useValue: mockDishService },
      ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(MenuComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

});

组件的代码是:

import { Component, OnInit, Inject } from '@angular/core';
import { Dish } from '../shared/dish';
import { DishService } from '../services/dish.service';
import { flyInOut, expand } from '../animations/app.animation';

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.scss'],
  // tslint:disable-next-line:use-host-property-decorator
  host: {
    '[@flyInOut]': 'true',
    'style': 'display: block;'
    },
  animations: [
    flyInOut(),
    expand()
  ]
})
export class MenuComponent implements OnInit {

  dishes!: Dish[];
  errMess: string;
  
  constructor(private dishService: DishService, 
    @Inject ('BaseURL') public baseURL) { }

  ngOnInit(): void {
    this.dishService.getDishes().subscribe((dishes => this.dishes = dishes), errMess => this.errMess = <any>errMess);
  }

}

我在运行 json-server --watch db.json 来模拟我从服务器获取信息时使用 baseURL 获取 db.json 文件的信息,因此我有一个名为的共享 .ts 文件baseurl.ts 代码如下:

export const baseURL = 'http://localhost:3000';

在 app.module.ts 中我导入了 const

import { baseURL } from './shared/baseurl';

我将它作为提供程序添加到同一个 app.module.ts 文件中:

providers: [
    { provide: 'BaseURL', useValue: baseURL }
  ],

感谢有人帮助解决此错误

【问题讨论】:

    标签: javascript angular typescript testing karma-jasmine


    【解决方案1】:

    问题 1:NullInjectorError

    此错误消息显示为您的DishComponent 需要注入BaseURL [@Inject ('BaseURL')]。

    NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]: NullInjectorError: 没有 BaseURL 的提供者!

    问题 1 的解决方案

    确保在providers 部分添加BaseURL 以进行单元测试。

    const baseUrl = "your Base URL";
    
    beforeEach(async () => {
      await TestBed.configureTestingModule({
        ...
        providers: [
          { provide: DishService, useValue: mockDishService },
          { provide: 'BaseURL', useValue: baseUrl },
        ]
      })
      .compileComponents();
    });
    

    问题 2:mockDishService.getDishes() 返回错误值

    MenuComponent,预计dishService.getDishes()返回Observable&lt;Menu[]&gt;Observable&lt;any[]&gt;类型的值。

    dishes!: Dish[];
    
    this.dishService.getDishes().subscribe((dishes => this.dishes = dishes), errMess => this.errMess = <any>errMess);
    

    mockDishService.getDishes()返回anyMenu类型的值,返回的数据是不匹配的。

    const mockDishService = {
      getDishes: () => {
        return {
          id: '000',
          name: 'nnnnn',
        };
      },
    };
    

    因此您将收到如下错误消息:

    TypeError: this.dishService.getDishes(...).subscribe 不是函数

    问题 2 的解决方案:

    确保mockDishService.getDishes() 返回Observable&lt;Menu[]&gt;Observable&lt;any[]&gt; 类型的值以匹配真实的dishService.getDishes()

    import { of } from 'rxjs';
    
    const mockDishService = {
      getDishes: () => {
        return of([
          {
            id: '000',
            name: 'nnnnn',
          },
        ]);
      },
    };
    

    Sample Solution on StackBlitz

    【讨论】:

    • 根据您的回答进行更改后,我收到此错误:错误:找到合成属性@flyInOut。请在您的应用程序中包含“BrowserAnimationsModule”或“NoopAnimationsModule”。所以我添加了 import {BrowserAnimationsModule } from '@angular/platform-b​​rowser/animations';并在beforeEach(async() => 中导入BrowserAnimationsModule,现在测试OK了,非常感谢!!!
    • 是的,请确保在开始单元测试之前提供组件所需的所有依赖项。您可以接受答案,因为它有帮助。谢谢。
    • 是的,我完全接受你的回答,非常感谢!!!
    猜你喜欢
    • 2020-11-02
    • 2019-07-23
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2021-12-27
    • 2023-03-06
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多