Angular2 - 在测试中模拟 RouteParams
Posted
技术标签:
【中文标题】Angular2 - 在测试中模拟 RouteParams【英文标题】:Angular2 - mocking RouteParams in test 【发布时间】:2016-04-18 08:26:54 【问题描述】:我在 Angular2 组件的测试中为 RouteParams 依赖项注入模拟时遇到了一些问题。我的一般想法是我可能缺少一些提供者。
测试失败:
无法解析“RouteParams”(?)的所有参数。确保所有参数都用 Inject 修饰 或具有有效的类型注释,并且“RouteParams”用 Injectable 装饰。有谁知道可能是什么问题?
import
it,
inject,
injectAsync,
describe,
beforeEach,
beforeEachProviders,
TestComponentBuilder
from 'angular2/testing';
import Component, provide from 'angular2/core';
import BaseRequestOptions, Http from 'angular2/http';
import MockBackend from 'angular2/http/testing';
import RouteParams, ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT from 'angular2/router';
// Load the implementations that should be tested
import Home from './home';
import Title from './providers/title';
describe('Home', () =>
// provide our implementations or mocks to the dependency injector
beforeEachProviders(() => [
Title,
Home,
provide(RouteParams, useValue: new RouteParams( id: '1' ) ),
BaseRequestOptions,
MockBackend,
provide(Http,
useFactory: function(backend, defaultOptions)
return new Http(backend, defaultOptions);
,
deps: [MockBackend, BaseRequestOptions]
),
provide(RouteParams,
useFactory: function()
return new RouteParams( 'id':'1' );
)
]);
it('should have a title', inject([ Home ], (home) =>
expect(home.title.value).toEqual('Angular 2');
));
it('should have a http', inject([ Home ], (home) =>
expect(!!home.http).toEqual(true);
));
it('should log ngOnInit', inject([ Home ], (home) =>
spyOn(console, 'log');
spyOn(console, 'info');
expect(console.log).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
home.ngOnInit();
expect(console.log).toHaveBeenCalled();
expect(console.info).toHaveBeenCalledWith('1');
));
);
【问题讨论】:
【参考方案1】:自己解决了这个问题,你使用 RouteProvider 来模拟
provide(RouteParams, useValue: new RouteParams( id: '1' ) )
import
it,
inject,
injectAsync,
describe,
beforeEach,
beforeEachProviders,
TestComponentBuilder
from 'angular2/testing';
import Component, provide from 'angular2/core';
import BaseRequestOptions, Http from 'angular2/http';
import MockBackend from 'angular2/http/testing';
import RouteParams, ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT from 'angular2/router';
// Load the implementations that should be tested
import Home from './home';
import Title from './providers/title';
describe('Home', () =>
// provide our implementations or mocks to the dependency injector
beforeEachProviders(() => [
Title,
Home,
provide(RouteParams, useValue: new RouteParams( id: '1' ) ),
BaseRequestOptions,
MockBackend,
provide(Http,
useFactory: function(backend, defaultOptions)
return new Http(backend, defaultOptions);
,
deps: [MockBackend, BaseRequestOptions]
)
]);
it('should have a title', inject([ Home ], (home) =>
expect(home.title.value).toEqual('Angular 2');
));
it('should have a http', inject([ Home ], (home) =>
expect(!!home.http).toEqual(true);
));
it('should log ngOnInit', inject([ Home ], (home) =>
spyOn(console, 'log');
spyOn(console, 'info');
expect(console.log).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
home.ngOnInit();
expect(console.log).toHaveBeenCalled();
expect(console.info).toHaveBeenCalledWith('1');
));
);
【讨论】:
【参考方案2】:适用于即使使用 Angular4
也能来到这里的人我只是继续创建了一个模拟。我想诀窍是模拟你需要的ActivatedRoute
的部分。对我来说,这样做了:
import ActivatedRoute, ParamMap from '@angular/router';
/**
* Mocking the ActivatedRoute which is injected in the Component on creation.
* This allows for easier testing as values can be set as needed.
*/
class MockActivatedRoute
paramMap = Observable.of(new Params());
/**
* Bare bones implementation of ParamMap used in mock. Further tests can expand
* on this implementation as needed.
*/
class Params implements ParamMap
keys: string[];
private routes: [key: string]: string|null =
subject: 'foo',
time: 'd-123-1',
device: 'all',
location: 'c-123'
;
constructor()
this.keys = Object.keys(this.routes);
has(name: string): boolean
throw new Error('Method not implemented.');
get(name: string): string|null
return this.routes[name];
getAll(name: string): string[]
throw new Error('Method not implemented.');
然后确保在您的测试模块中提供模拟服务而不是真实的ActivatedRoute
:
providers: [
provide: ActivatedRoute,
useValue: new MockActivatedRoute(),
]
为了完成,我在我正在测试的组件中使用它的方式:
ngOnInit()
this.route.paramMap
.map((params: ParamMap) => params.get('subject') as string)
.subscribe((subject: string) => this.subject = subject);
【讨论】:
以上是关于Angular2 - 在测试中模拟 RouteParams的主要内容,如果未能解决你的问题,请参考以下文章
Angular2(TypeScript)中的单元测试/模拟窗口属性
Angular 2 单元测试组件,模拟 ContentChildren
Angular 2:如何在单元测试时模拟 ChangeDetectorRef