我试图测试在其构造函数中注入了应用程序路由器的服务。遵循Julie Ralph在AngularConnect conf 2015(及其存储库:https://github.com/juliemr/ng2-test-seed)中提出的建议, 我使用了Karma和Jasmine。
它遵循要测试的示例服务:
import { Router } from 'angular2/router';
export class ExampleService {
constructor(router : Router) {
this._router = router;
}
//...
}
现在,我只是断言真相。它遵循服务测试:
import { it, describe, expect, inject, beforeEachProviders, MockApplicationRef } from 'angular2/testing';
import { ROUTER_PROVIDERS } from 'angular2/router';
import { provide, ApplicationRef } from 'angular2/core';
import { ExampleService } from 'example-service.js';
describe('ExampleService', () => {
beforeEachProviders(() => [
ROUTER_PROVIDERS, ExampleService,
provide(ApplicationRef, { useClass: MockApplicationRef })
]);
it('should validate the truth', inject([ExampleService], (exService) => {
expect(true).toBeTruthy();
}));
});
当我运行测试时(> karma start karma.config.js),我得到一个TypeError:无法读取属性' length'为null
查看router.js源代码,看起来我应该在注入路由器之前引导至少一个组件。在那儿 在测试中注入路由器依赖项的简单方法吗?
Stacktrace:
原始异常:TypeError:无法读取属性'长度'为null 原装STACKTRACE: TypeError:无法读取属性' length'为null 在routerPrimaryComponentFactory(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/router.js:2963:27) 在Injector._instantiate(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11920:19) 在Injector._instantiateProvider(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21) 在Injector._new(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19) 在InjectorDynamicStrategy.getObjByKeyId(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42) 在Injector._getByKeyDefault(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33) at Injector._getByKey(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21) at Injector._getByDependency(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21) 在Injector._instantiate(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32) 在Injector._instantiateProvider(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21) 在Injector._new(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19) 在InjectorDynamicStrategy.getObjByKeyId(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42) 在Injector._getByKeyDefault(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33) at Injector._getByKey(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21) at Injector._getByDependency(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21) 在Injector._instantiate(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32) 在Injector._instantiateProvider(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21) 在Injector._new(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19) 在InjectorDynamicStrategy.getObjByKeyId(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42) 在Injector._getByKeyDefault(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33) at Injector._getByKey(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21) at Injector._getByDependency(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21) 在Injector._instantiate(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32) 在Injector._instantiateProvider(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21) 在Injector._new(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19) 在InjectorDynamicStrategy.getObjByKeyId(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42) 在Injector._getByKeyDefault(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33) at Injector._getByKey(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21) 在Injector.get(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11804:19) 在C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2477:25 在Array.map(本机) 在Array.map(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/es6-shim/es6-shim.js:1113:14) 在FunctionWithParamTokens.execute(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2476:33) 在C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2601:25 在Zone.run(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2-polyfills.js:138:17) 在Zone.run(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2544:30) at runInTestZone(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2588:23) 在对象。 (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2600:33) at attemptAsync(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24) 在QueueRunner.run(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9) 在QueueRunner.execute(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1762:10) 在Spec.Env.queueRunnerFactory(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:627:35) 在Spec.execute(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:353:10) at Object.fn(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2360:37) at attemptAsync(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24) 在QueueRunner.run(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9) 在QueueRunner.execute(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1762:10) 在Env.queueRunnerFactory(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:627:35) at Object.fn(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2345:13) at attemptAsync(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24) 在QueueRunner.run(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9) 在C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1801:16 在C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1745:9 在queueRunnerFactory.onComplete(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2348:17) 在QueueRunner.clearStack(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:605:9) 在QueueRunner.run(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1784:12) 在C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1801:16 在C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1745:9 完成后(C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:365:9)
答案 0 :(得分:6)
问题解决了,只需要提供ROUTER_PRIMARY_COMPONENT。
import {ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
class MockPrimaryComponent {
}
beforeEachProviders(() => [
ROUTER_PROVIDERS,
provide(ROUTER_PRIMARY_COMPONENT, {useClass: MockPrimaryComponent}),
ExampleService,
provide(ApplicationRef, { useClass: MockApplicationRef })
]);
答案 1 :(得分:3)
我知道这篇文章与旧路由器有关,但我认为回答这个问题可能会有用。使用角度版本rc.1和新路由器,我使用路由器进行单元测试,包括测试navigateByUrl,在angular中使用此测试作为灵感:https://github.com/angular/angular/blob/master/modules/%40angular/router/test/integration_spec.ts
为我节省了很多麻烦
这是一个有效的例子
import {setBaseTestProviders,beforeEachProviders,inject,it,describe,expect,beforeEach} from '@angular/core/testing'
import { Component,provide} from '@angular/core';
import {Routes,ROUTER_DIRECTIVES,Route} from "@angular/router";
import {ComponentResolver} from '@angular/core';
import {Router,RouterOutletMap,RouteSegment,RouterUrlSerializer,DefaultRouterUrlSerializer} from '@angular/router';
import {SpyLocation} from '@angular/common/testing';
import {Location} from '@angular/common';
import {ComponentFixture, TestComponentBuilder} from '@angular/compiler/testing';
import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from '@angular/platform-browser-dynamic/testing';
@Component({
selector: 'some-component',
template: `Blah!`,
directives: [ROUTER_DIRECTIVES]
})
export class SomeComponent {
}
@Component({
selector: 'another-component',
template: `Blah!`,
directives: [ROUTER_DIRECTIVES]
})
export class AnotherComponent {
}
@Component({
selector: 'root-cmp',
template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES]
})
@Routes([
new Route({path: '/some-path',component:SomeComponent}),
new Route({path: '/another-path',component:AnotherComponent})
])
export class RootCmp {
}
export const PROVIDERS_TESTING = [
provide(RouterUrlSerializer, {useClass: DefaultRouterUrlSerializer}),
RouterOutletMap,
provide(Location, {useClass: SpyLocation}),
provide(RouteSegment, {useFactory: (r) => r.routeTree.root, deps: [Router]}),
provide(Router,{
useFactory: (resolver, urlParser, outletMap, location) => new Router(
"RootComponent", RootCmp, resolver, urlParser, outletMap, location),
deps: [ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location]
}
),
]
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,[TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,PROVIDERS_TESTING]);
it('some test',inject([Router, TestComponentBuilder, Location], (router:Router, tcb:TestComponentBuilder, location:Location) => {
return new Promise((resolve,reject)=>{
tcb.createAsync(RootCmp).then(fixture=>{
router.navigateByUrl('/some-path').then(()=>{
expect(location.path()).toEqual('/some-path');
resolve()
})
})
})
}))
it('another test',inject([Router, TestComponentBuilder, Location], (router:Router, tcb:TestComponentBuilder, location:Location) => {
return new Promise((resolve,reject)=>{
tcb.createAsync(RootCmp).then(fixture=>{
router.navigateByUrl('/another-path').then(()=>{
expect(location.path()).toEqual('/another-path');
resolve()
})
})
})
}))