如何在测试中模拟 NavParams?
How to mock NavParams in tests?
这可能是 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)
时它们都期望得到不同的结果,模拟变得越来越棘手。
有没有人找到解决这种情况的方法?
您可以通过实施自己的 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;
}
}
然后在每个测试中您可以访问该服务并设置您自己的参数对象。
beforeEach(() => {
NavParamsMock.setParams(ownParams); //set your own params here
TestBed.configureTestingModule({
providers: [
{provide: NavParams, useClass: NavParamsMock},
]
});
})
我用我自己的这种技术变体修改了@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;
}
}
与其模拟 class,最简单的方法是创建 NavParams
class 的实例,然后使用它。 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()
每次)。
这是一个有多个参数的例子
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()
})
这可能是 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)
时它们都期望得到不同的结果,模拟变得越来越棘手。
有没有人找到解决这种情况的方法?
您可以通过实施自己的 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;
}
}
然后在每个测试中您可以访问该服务并设置您自己的参数对象。
beforeEach(() => {
NavParamsMock.setParams(ownParams); //set your own params here
TestBed.configureTestingModule({
providers: [
{provide: NavParams, useClass: NavParamsMock},
]
});
})
我用我自己的这种技术变体修改了@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;
}
}
与其模拟 class,最简单的方法是创建 NavParams
class 的实例,然后使用它。 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()
每次)。
这是一个有多个参数的例子
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()
})