Angular 2 (Mock Ionic2) -- App 没有提供者
Angular 2 (Mock Ionic2) -- No provider for App
我正在尝试为我的应用程序创建 spec.ts
。遗憾的是,这是使用 ionic-angular
中的 LoadingController。现在,当我尝试配置模块时,我需要为其提供 LoadingController(因为它位于模块的构造函数中)。
我目前 运行 遇到的问题是要为 LoadingController 提供 App
object/instance。 (_app: App
参数)
我很绝望所以我问了 Ionic 自己。 github #8539
但他们关闭了我的问题,因为这是一个问题而不是一个问题,尽管我在意识到这一点时遇到了问题,但他们没有回应。如果这是 impossible/no 知道怎么做的,那将是一种耻辱,因为它是一个非常酷的功能,它不仅影响 LoadingController,f.e。 AlertController 和 ToastController 也受此影响。
我的 testbed 配置 atm:
TestBed.configureTestingModule({
declarations: [EventsPage],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{provide: APICaller, useValue: mockAPICaller},
{provide: NavController, useValue: mockNavController },
{provide: LoadingController, useValue: ???????}, //it seems like everything I try to enter here fails.
],
imports: [FormsModule]
});
以及 EventsPage 构造函数:
constructor(public apiCaller: APICaller, public navCtrl: NavController,
public loadingCtrl: LoadingController){}
编辑:LoadingController
的用法
getEvents() {
// setup a loadingscreen
let loading = this.loadingCtrl.create({
content: "Loading..."
});
// present the loadingscreen
loading.present();
// reset the noEvents boolean.
this.noEvents = true;
// call the api and get all events
this.apiCaller.getEvents()
.subscribe(response => {
// response is list of events
this.events = response;
// if the event is not empty, set noEvents to false.
if (this.events.length > 0) {
this.noEvents = false;
}
// close the loading message.
loading.dismiss();
});
}
这将导致此 loadingspinner(具有不同的文本)
对于这种类型的东西,您可能不想在 UI 中测试任何东西(关于使用 LoadingController
)。您应该测试的是组件的行为。因此,当您为 LoadingController
创建模拟时,您要做的是监视关键方法,并且您的期望应该进行测试以确保您正在调用 LoadingController
上的方法。这样做你可以编写像
这样的测试
expect(loadingController.someMethod).toHaveBeenCalled();
// or
expect(loadingController.someMethod).toHaveBeenCalledWith(args);
您的模拟也不必遵循被模拟项目的实际结构。例如 LoadingController.create
return 是一个 Loading
对象。在你的模拟中,你不需要这个。如果你愿意,你可以 return 模拟本身,当调用 create
时,在模拟中只有 Loading
会有的方法。
请记住,您只是在测试控制器的行为。模拟 LoadingController
实际做什么并不重要,只要您能够调用这些方法,并检查测试以确保它们被调用 当 它们是预计会被调用。除此之外,您应该 假设 真正的 LoadingController
有效。
所以你可以有类似的东西
let mockLoadingController = {
// Tried `create: jasmine.createSpy('create').and.returnValue(this)
// seem this doesn't work. We just create the spy later
create: (args: any) => { return this; },
present: jasmine.createSpy('present'),
dismiss: jasmine.createSpy('dismiss')
};
spyOn(mockLoadingController, 'create').and.returnValue(mockLoadingController);
{ provide: LoadingController, useValue: mockLoadingController }
然后在你的测试中你可以做类似
的事情
it('should create loader with args ...', () => {
...
expect(mockLoadingController.create).toHaveBeenCalledWith({...})
})
it('should present the loader', () => {
...
expect(mockLoadingController.present).toHaveBeenCalled();
})
it('should dismiss the loader when the api call returns', async(() => {
..
expect(mockLoadingController.dismiss).toHaveBeenCalled();
}))
这是我现在用来测试的
class LoadingController {
create(args: any) { return this; }
present() {}
dismiss() {}
}
@Component({
template: ''
})
class TestComponent {
constructor(private loadingController: LoadingController) {}
setEvents() {
let loading = this.loadingController.create({hello: 'world'});
loading.present();
loading.dismiss();
}
}
describe('component: TestComponent', () => {
let mockLoadingController;
beforeEach(async(() => {
mockLoadingController = {
create: (args: any) => { return this; },
present: jasmine.createSpy('present'),
dismiss: jasmine.createSpy('dismiss')
};
spyOn(mockLoadingController, 'create').and.returnValue(mockLoadingController);
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [
{ provide: LoadingController, useValue: mockLoadingController }
]
});
}));
it('should calling loading controller', () => {
let comp = TestBed.createComponent(TestComponent).componentInstance;
comp.setEvents();
expect(mockLoadingController.create).toHaveBeenCalledWith({ hello: 'world'});
expect(mockLoadingController.present).toHaveBeenCalled();
expect(mockLoadingController.dismiss).toHaveBeenCalled();
});
});
另请参阅:
我正在尝试为我的应用程序创建 spec.ts
。遗憾的是,这是使用 ionic-angular
中的 LoadingController。现在,当我尝试配置模块时,我需要为其提供 LoadingController(因为它位于模块的构造函数中)。
我目前 运行 遇到的问题是要为 LoadingController 提供 App
object/instance。 (_app: App
参数)
我很绝望所以我问了 Ionic 自己。 github #8539
但他们关闭了我的问题,因为这是一个问题而不是一个问题,尽管我在意识到这一点时遇到了问题,但他们没有回应。如果这是 impossible/no 知道怎么做的,那将是一种耻辱,因为它是一个非常酷的功能,它不仅影响 LoadingController,f.e。 AlertController 和 ToastController 也受此影响。
我的 testbed 配置 atm:
TestBed.configureTestingModule({
declarations: [EventsPage],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{provide: APICaller, useValue: mockAPICaller},
{provide: NavController, useValue: mockNavController },
{provide: LoadingController, useValue: ???????}, //it seems like everything I try to enter here fails.
],
imports: [FormsModule]
});
以及 EventsPage 构造函数:
constructor(public apiCaller: APICaller, public navCtrl: NavController,
public loadingCtrl: LoadingController){}
编辑:LoadingController
的用法getEvents() {
// setup a loadingscreen
let loading = this.loadingCtrl.create({
content: "Loading..."
});
// present the loadingscreen
loading.present();
// reset the noEvents boolean.
this.noEvents = true;
// call the api and get all events
this.apiCaller.getEvents()
.subscribe(response => {
// response is list of events
this.events = response;
// if the event is not empty, set noEvents to false.
if (this.events.length > 0) {
this.noEvents = false;
}
// close the loading message.
loading.dismiss();
});
}
这将导致此 loadingspinner(具有不同的文本)
对于这种类型的东西,您可能不想在 UI 中测试任何东西(关于使用 LoadingController
)。您应该测试的是组件的行为。因此,当您为 LoadingController
创建模拟时,您要做的是监视关键方法,并且您的期望应该进行测试以确保您正在调用 LoadingController
上的方法。这样做你可以编写像
expect(loadingController.someMethod).toHaveBeenCalled();
// or
expect(loadingController.someMethod).toHaveBeenCalledWith(args);
您的模拟也不必遵循被模拟项目的实际结构。例如 LoadingController.create
return 是一个 Loading
对象。在你的模拟中,你不需要这个。如果你愿意,你可以 return 模拟本身,当调用 create
时,在模拟中只有 Loading
会有的方法。
请记住,您只是在测试控制器的行为。模拟 LoadingController
实际做什么并不重要,只要您能够调用这些方法,并检查测试以确保它们被调用 当 它们是预计会被调用。除此之外,您应该 假设 真正的 LoadingController
有效。
所以你可以有类似的东西
let mockLoadingController = {
// Tried `create: jasmine.createSpy('create').and.returnValue(this)
// seem this doesn't work. We just create the spy later
create: (args: any) => { return this; },
present: jasmine.createSpy('present'),
dismiss: jasmine.createSpy('dismiss')
};
spyOn(mockLoadingController, 'create').and.returnValue(mockLoadingController);
{ provide: LoadingController, useValue: mockLoadingController }
然后在你的测试中你可以做类似
的事情it('should create loader with args ...', () => {
...
expect(mockLoadingController.create).toHaveBeenCalledWith({...})
})
it('should present the loader', () => {
...
expect(mockLoadingController.present).toHaveBeenCalled();
})
it('should dismiss the loader when the api call returns', async(() => {
..
expect(mockLoadingController.dismiss).toHaveBeenCalled();
}))
这是我现在用来测试的
class LoadingController {
create(args: any) { return this; }
present() {}
dismiss() {}
}
@Component({
template: ''
})
class TestComponent {
constructor(private loadingController: LoadingController) {}
setEvents() {
let loading = this.loadingController.create({hello: 'world'});
loading.present();
loading.dismiss();
}
}
describe('component: TestComponent', () => {
let mockLoadingController;
beforeEach(async(() => {
mockLoadingController = {
create: (args: any) => { return this; },
present: jasmine.createSpy('present'),
dismiss: jasmine.createSpy('dismiss')
};
spyOn(mockLoadingController, 'create').and.returnValue(mockLoadingController);
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [
{ provide: LoadingController, useValue: mockLoadingController }
]
});
}));
it('should calling loading controller', () => {
let comp = TestBed.createComponent(TestComponent).componentInstance;
comp.setEvents();
expect(mockLoadingController.create).toHaveBeenCalledWith({ hello: 'world'});
expect(mockLoadingController.present).toHaveBeenCalled();
expect(mockLoadingController.dismiss).toHaveBeenCalled();
});
});
另请参阅: