这可能只是一个Ionic 2问题,因为我没有在Angular 2文档中看到NavParams,但是有些概念可能会翻译,所以我标记了两者。
鉴于我为了侦听传入的参数而调用navparams.get('somekey')
,在测试中模拟NavParams是很棘手的。
例如,以下是我目前的工作方式:
export class NavParamsMock {
public get(key): any {
return String(key) + 'Output';
}
}
这适用于非常基本的测试,但是如果我有一个组件,我必须测试gets
特定类型的Object
,例如User
。
然后,我可以做类似
的事情export class NavParamsMock {
public get(key): any {
if (key === 'user') {
return new User({'name':'Bob'})
}
return String(key) + 'Output';
}
}
但是,如果您想在另一个测试中使用get(user)
,或者甚至是另一个组件的规范,则这不起作用。假设您在2个不同的组件中使用NavParams,并且当您执行get(user)
时它们都期望不同的结果,模拟变得越来越棘手。
有没有人找到这种情况的解决方案?
答案 0 :(得分:12)
您可以通过实施自己的setter方法获得您选择的价值。
export class NavParamsMock {
static returnParam = null;
public get(key): any {
if (NavParamsMock.returnParam) {
return NavParamsMock.returnParam
}
return 'default';
}
static setParams(value){
NavParamsMock.returnParam = value;
}
}
然后在每个测试中,您都可以访问该服务并设置自己的params对象。
beforeEach(() => {
NavParamsMock.setParams(ownParams); //set your own params here
TestBed.configureTestingModule({
providers: [
{provide: NavParams, useClass: NavParamsMock},
]
});
})
答案 1 :(得分:6)
最简单的方法是创建NavParams
类的实例,然后使用它,而不是模拟类。 NavParams
使data
属性可公开分配,因此可以根据需要在每个测试中对其进行修改。
以下示例假设您的网页看起来像这样:
@IonicPage()
@Component({...})
export class YourPage {
private data: string;
constructor(navParams: NavParams) {
this.data = navParams.get('data');
}
}
即,您在页面navParams.get()
,constructor
,ionViewDidLoad()
或类似的初始化函数中调用ngOnInit()
。在这种情况下,要修改NavParams
数据并确保其正确使用,您需要修改测试注入navParams.data
属性,然后重新生成页面:
import {IonicModule, NavParams} from 'ionic-angular';
import {ComponentFixture, TestBed} from '@angular/core/testing';
describe('YourPage', () => {
let fixture: ComponentFixture<YourPage>;
let component: YourPage;
const data = {data: 'foo'};
const navParams = new NavParams(data);
function generateFixture() {
fixture = TestBed.createComponent(YourPage);
component = fixture.componentInstance;
fixture.detectChanges();
}
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [YourPage],
imports: [
IonicModule.forRoot(YourPage),
],
providers: [
{provide: NavParams, useValue: navParams},
]
});
generateFixture();
});
describe('NavParams', () => {
it('should use injected data', () => {
expect(component['data']).toEqual('foo');
});
it('should use new injected data', () => {
const newData = {data: 'bar'};
navParams.data = newData;
generateFixture();
expect(component['data']).toEqual('bar');
});
});
});
如果您的网页在任何地方调用navParams.get('key')
而不是分配给私有成员,那么只需在每次测试中重新分配navParams.data
属性就足够了(每次都不需要调用generateFixture()
)。
答案 2 :(得分:4)
我用我自己的这种技术变体修改了@ raj的答案。 @ raj只允许你设置一个参数。我允许使用多个参数进行密钥值存储。
export class NavParamsMock {
static returnParams: any = {};
public get(key): any {
if (NavParamsMock.returnParams[key]) {
return NavParamsMock.returnParams[key];
}
return 'No Params of ' + key + ' was supplied. Use NavParamsMock.setParams('+ key + ',value) to set it.';
}
static setParams(key,value){
NavParamsMock.returnParams[key] = value;
}
}
答案 3 :(得分:0)
以下是多个参数的示例
<强> NavParamsMock 强>
export class NavParamsMock {
static returnParams: any = {}
public get (key): any {
if (NavParamsMock.returnParams[key]) {
return NavParamsMock.returnParams[key]
}
}
static setParams (key, value): any {
NavParamsMock.returnParams[key] = value
}
}
将以下
添加到 TestBed 提供商{provide: NavParams, useClass: NavParamsMock}
单元测试
it('i am a unit test', () => {
const navParams = fixture.debugElement.injector.get(NavParams)
navParams.get =
jasmine
.createSpy('get')
.and
.callFake((param) => {
const params = {
'param1': 'value',
'param2': 'value'
}
return params[param]
})
comp.ionViewDidLoad()
})