RouterTestingModule 不提供 Location 的提供者
RouterTestingModule not providing provider for Location
我正在对使用另外两个组件的 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');
}));
});
早些时候,我通过显式添加提供程序使代码工作。但我认为情况不应该如此。我不确定为什么只使用 RouterTestingModule
不起作用。
解决方法
providers:[...,
{provide: Location, useClass: SpyLocation},
{provide: LocationStrategy, useClass: MockLocationStrategy},
{provide: NgModuleFactoryLoader, useClass: SpyNgModuleFactoryLoader}]
实际问题是由于未知原因选择了错误的 Location
定义。当我添加 import {Location} from "@angular/common";
时,测试没有明确添加 providers
之所以选择了错误的 Location 以及为什么 import {Location} from "@angular/common";
有所帮助,是因为在不导入它的情况下,TypeScript 实际上认为您想要使用 window.location
的类型,这与你要找的那个。
由于类型是从 angular 的 DI 注册表中检索所需实例的标记,因此如果您使用错误的类型,您将得不到任何东西。当您在 IDE 中注释掉导入和 'click through' Location
类型时,您会看到选择的类型实际上是 DOM 接口,而不是 Angular 执行。一旦你的 tsconfig.json 中有 "lib": ["dom"]
,这个 DOM 接口就隐含在那里。
从 angular 导入 Location
显式地从 DOM 中导入 Location
,选择正确的类型并在 [= 中找到正确的 Location
实例31=] 的 DI 注册表。
实际上很容易犯错误(我自己犯的),因为即使你忘记导入 Location
,DOM Location
也会被选中,你会得到IDE 中完全没有反馈,您会想知道为什么 DI 会失败。
我正在对使用另外两个组件的 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');
}));
});
早些时候,我通过显式添加提供程序使代码工作。但我认为情况不应该如此。我不确定为什么只使用 RouterTestingModule
不起作用。
解决方法
providers:[...,
{provide: Location, useClass: SpyLocation},
{provide: LocationStrategy, useClass: MockLocationStrategy},
{provide: NgModuleFactoryLoader, useClass: SpyNgModuleFactoryLoader}]
实际问题是由于未知原因选择了错误的 Location
定义。当我添加 import {Location} from "@angular/common";
providers
之所以选择了错误的 Location 以及为什么 import {Location} from "@angular/common";
有所帮助,是因为在不导入它的情况下,TypeScript 实际上认为您想要使用 window.location
的类型,这与你要找的那个。
由于类型是从 angular 的 DI 注册表中检索所需实例的标记,因此如果您使用错误的类型,您将得不到任何东西。当您在 IDE 中注释掉导入和 'click through' Location
类型时,您会看到选择的类型实际上是 DOM 接口,而不是 Angular 执行。一旦你的 tsconfig.json 中有 "lib": ["dom"]
,这个 DOM 接口就隐含在那里。
从 angular 导入 Location
显式地从 DOM 中导入 Location
,选择正确的类型并在 [= 中找到正确的 Location
实例31=] 的 DI 注册表。
实际上很容易犯错误(我自己犯的),因为即使你忘记导入 Location
,DOM Location
也会被选中,你会得到IDE 中完全没有反馈,您会想知道为什么 DI 会失败。