RouterTestingModule不提供位置的提供程序

时间:2018-12-17 10:28:59

标签: angular angular6 angular-routing angular-testing

我正在对使用其他两个组件的Component进行单元测试。单击按钮会创建其他组件

.html

    <div id="homepage-top-div" class="homepage-component-css-grid-container">  ...
        <button id="get-question-list-button" [routerLink]="questionListRouterLink" class="btn content-div__button--blue css-grid-item-button-div btn-sm">See Questions</button>
      </div>
      <div id="practice-component-top-div" class="css-grid-container-div common-styles-div--white"> <!-- 4 rows, 1 column-->
...
        <button id="new-question-button" [routerLink]="newQuestionRouterLink"  class="btn content-div__button--blue css-grid-item-button-div btn-sm">Create a Question</button>
      </div>
    </div>

.ts

export class HomepageContentComponentComponent implements OnInit {

  public questionListRouterLink="/practice-question-list";
  public newQuestionRouterLink="/new-practice-question";


  constructor() {

  }

  ngOnInit() {
  }

}

我创建了一个规范,但运行它时遇到以下错误-Error: StaticInjectorError[Location]: NullInjectorError: No provider for Location!

规格是

import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import { HomepageContentComponentComponent } from './homepage-content-component.component';
import {RouterTestingModule} from "@angular/router/testing";
import {AppRoutingModule} from "../app-routing.module";
import {Router} from "@angular/router";
import {routes} from '../app-routing.module';
import {NewPracticeQuestionComponent} from "../new-practice-question/new-practice-question.component";
import {PraticeQuestionListComponent} from "../pratice-question-list/pratice-question-list.component";
import {NgModule} from "@angular/core";
import {AppModule} from "../app.module";

fdescribe('HomepageContentComponentComponent', () => {
  let component: HomepageContentComponentComponent;
  let fixture: ComponentFixture<HomepageContentComponentComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports:[
        AppModule,
        AppRoutingModule,
        RouterTestingModule.withRoutes(routes) //<-- I SUPPOSE THIS STEP SHOULD PROVIDE ROUTERTESTINGMODULE WITH PROVIDERS FOR LOCATION BUT IT SEEMS IT ISN'T
      ],
      declarations: [ HomepageContentComponentComponent,
                  NewPracticeQuestionComponent,
        PraticeQuestionListComponent]
    })
    .compileComponents();
  }));

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

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

  it('should navigate to New Questions Component when New Question button is clicked',fakeAsync(()=>{
    let router:Router;
    let location:Location;
    router = TestBed.get(Router);
    location = TestBed.get(Location);
    console.log('initial router is ',router);
    console.log('initial location is ',location);
    router.initialNavigation();
    router.navigate(['new-practice-question']);
    tick();
    console.log('new router is ',router);
    console.log('new location is ',location);

    expect(location.pathname).toBe('/new-practice-question');
  }));
});

2 个答案:

答案 0 :(得分:2)

之前,我通过显式添加提供程序来使代码正常工作。但我认为事实并非如此。我不确定为什么仅使用RouterTestingModule无效。

解决方法

providers:[...,
{provide: Location, useClass: SpyLocation},
        {provide: LocationStrategy, useClass: MockLocationStrategy},
        {provide: NgModuleFactoryLoader, useClass: SpyNgModuleFactoryLoader}]

实际的问题是由于未知原因而选择了错误的Location定义。当我添加providers

时,该测试无需显式添加import {Location} from "@angular/common";就可以工作

答案 1 :(得分:1)

为什么选择了错误的位置以及import {Location} from "@angular/common";的原因是TypeScript实际上认为您不希望使用window.location的类型,所以它与类型完全不同。您正在寻找。

由于类型是从angular的DI注册中心检索所需实例的令牌,因此,如果使用错误的类型,则不会得到任何信息。当您注释掉导入并在IDE中“点击” Location类型时,您会看到所选择的类型实际上是DOM接口,而不是Angular实现。一旦您在 tsconfig.json 中拥有"lib": ["dom"],该DOM接口就会隐式存在。

从棱角的Location的DOM中显式地导入Location,在Angle的DI注册表中选择正确的类型并找到正确的Location实例。

实际上是很容易犯的错误(我自己做的),因为即使您忘记导入Location,也会选择DOM Location,并且您在IDE上没有任何反馈所有人,您都纳闷,为什么DI会失败。