I have this scenario problem:
In a Ionic/Angular project(ionic v3/Angular v5) I have the component SuppliedVanContainerComponent which extends the abstract class AbstractLoadingClass and this class extends another abstract class AbstractSubscriberClass.
The AbstractLoadingClass use the LoadingController
an ionic-angular service for showing the spinner and it used by SuppliedVanContainerComponent when call the showLoading methods.
The problem: When I can use unit test with jasmine it show me those error:
TypeError: Cannot read properties of undefined (reading '_getPortal')
And when I go to mock the LoadingController with jasmine.createSpyObj, it show me another error and is:
TypeError: this.loading.present is not a function
How can I fix it or can I test with abstract classes?
SuppliedVanContainerComponent
export class SuppliedVanContainerComponent extends AbstractLoadingClass
constructor(loadingCtrl: LoadingController) {
super(loadingCtrl);
}
ngOnInit(){
this.showLoading();
}
AbstractLoadingClass
import {Loading, LoadingController} from 'ionic-angular';
import {LoadingOptions} from 'ionic-angular/umd/components/loading/loading-options';
import {AbstractSubscriberClass} from './abstract-subscriber.class';
export abstract class AbstractLoadingClass extends AbstractSubscriberClass {
private loading: Loading;
protected constructor(public loadingCtrl: LoadingController) {
super();
}
private getCreateLoading(opts?: LoadingOptions) {
return this.loadingCtrl.create(opts);
}
showLoading() {
this.loading = this.getCreateLoading({content: ''});
this.loading.present();
this.loading.setContent('');
}
hideLoading() {
this.loading.dismiss();
}
}
The jasmine test with error
...
let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', {
create: {content: ''},
})
...
{provide: LoadingController, useValue: fakeLoadingController},
CodePudding user response:
Thanks @AliF50 the i have two solutions and i post it, First Solution:
....
let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', ['create'])
......
providers: [
....
{provide: LoadingController, useValue: fakeLoadingController},
]
....
beforeEach(() => {
fixture = TestBed.createComponent(SuppliedVanContainerComponent);
fakeLoadingController.create.and.returnValue({present: () => null, setContent: () => null, dismiss: () => null});
component = fixture.componentInstance;
fixture.detectChanges();
});
And it's work as simple and without spy or test with LoaderController (just mocking).
If you would work with Loading and spy , to be set in this mode:
.....
let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', ['create'])
let fakeLoadingObject = jasmine.createSpyObj<Loading>('Loading', ['present', 'setContent', 'dismiss']);
.....
providers: [
...
{provide: LoadingController, useValue: fakeLoadingController},
{provide: Loading, useValue: fakeLoadingObject},
]
....
beforeEach(() => {
fixture = TestBed.createComponent(SuppliedVanContainerComponent);
dailyReportsModel = TestBed.get(DailyReportsModel);
fakeLoadingController.create.and.returnValue(fakeLoadingObject);
component = fixture.componentInstance;
fixture.detectChanges();
});
....
it('test fakeLoadingObject', () => {
expect(fakeLoadingObject.present).toHaveBeenCalled();
})
Thanks at @AliF50
CodePudding user response:
I think you're mocking it incorrectly, try this:
let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', ['create']);
...
{provide: LoadingController, useValue: fakeLoadingController},
...
// before fixture = ..., add this line
fakeLoadingController.create.and.returnValue({ present: () => null, setContent: () => null, dismiss: () => null });
// Or if you want spies on present, setContent, dismiss, you could do
let fakeLoadingObject = jasmine.createSpyObj<any>('FakeLoadingObject', ['present', 'setContent', 'dismiss']);
// then the line above becomes
fakeLoadingController.create.and.returnValue(fakeLoadingObject);
// And then you should have a handle of something like this:
expect(fakeLoadingObject.present).toHaveBeenCalled();