-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
General Testing Help / Advice #191
Comments
We have been using the new keyboard without issues for a while.
…On Fri, 9 Jun 2017 at 01:31, Ka Mok ***@***.***> wrote:
I ran into this Issues where using the new Keyboard would cause a no
provider error.
You can replicate it by using the new ionic native keyboard import.
ionic-team/ionic-plugin-keyboard#281
<ionic-team/ionic-plugin-keyboard#281>
Any ideas on why this happens?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#191 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AG5tSPqdV8xUk2_60r_csT1tGHvVzjr3ks5sCBO3gaJpZM4LI56M>
.
|
@lathonez I figured out the new ionic Keyboard from |
@kamok @lathonez I've been grappling with the problem I think you're describing, when to use TestUtils and when you need a more tailored testmodule. I have a project where I'm using the TestUtil to provide the base "ambient" providers but then I have an additional parameter that allows me to pass in additional providers that I may like a reference to or as additional dependencies. Have you guys come up with a better way? TestUtils public static beforeEachCompiler(components: any[], providers: any[]): Promise<{ fixture: any, instance: any }> {
return TestUtils.configureIonicTestingModule(components, providers)
.compileComponents().then(() => {
let fixture: any = TestBed.createComponent(components[0]);
return {
fixture: fixture,
instance: fixture.debugElement.componentInstance,
};
});
}
public static configureIonicTestingModule(components: Array<any>, componentProviders: any[]): typeof TestBed {
let coreProviders: any[] = [
App,
DomController,
GestureController,
{provide: Keyboard, useFactory: () => KeyboardMock.instance()},
{provide: MenuController, useFactory: () => MenuControllerMock.instance()},
{provide: Form, useFactory: () => FormMock.instance()},
{provide: Config, useFactory: () => ConfigMock.instance()},
{provide: TranslateService, useFactory: (TranslateServiceMock.instance)},
{provide: Platform, useFactory: () => PlatformMock.instance()},
];
let providers: any[] = coreProviders.concat(componentProviders);
return TestBed.configureTestingModule({
imports: [IonicModule, CommonModule],
declarations: [components, TranslatePipeMock ],
providers: providers
});
} which in use looks something like: beforeEach(async(() => {
form = FormGroupMock.instance(true, formVal);
viewCtrl = ViewControllerMock.instance();
formBuilder = FormBuilderMock.instance(form);
settingsSrvc = SettingsServiceMock.instance();
dateSrvc = DateServiceMock.instance();
let providers: any[] = [
{provide: FormBuilder, useFactory: () => formBuilder},
{provide: SettingsService, useFactory: () => settingsSrvc},
{provide: ViewController, useFactory: () => viewCtrl},
{provide: DateService, useFactory: () => dateSrvc}
];
return TestUtils.beforeEachCompiler([ReportCreatePage], providers)
.then(compiled => {
fixture = compiled.fixture;
instance = compiled.instance;
classUnderTest = fixture.componentInstance;
fixture.detectChanges();
});
}
)); |
The way I do this is defining different "sets" of providers for different usages, and assigning each to a static variable against TestUtils. Instead of declaring the providers in the beforeEach and passing them in, I pass through this variable It's basically the same as what you have there, I just have lots of spec and it saves me from importing the additional providers each time. In practice I think I have four different sets that I use. |
Hi. I have trouble testing a component containg a FAB. Maybe you can give me a hint how to solve this. https://stackoverflow.com/questions/45711222/how-to-test-a-floating-action-button-in-ionic2 |
The error is coming from
So we need to look at our platform mock: https://github.com/stonelasley/ionic-mocks/blob/master/src/angular/platform.ts#L26 Adding this line solves for me. Please raise a PR against ionic-mocks to fix! instance.registerListener.and.returnValue(() => {}); Thanks |
how is everyone testing classes with asynchronous tasks in their constructor? I've started using the following approach but I'd love to find a better way. class MyClass {
constructor(platform: Platform, service: MyService) {
this.platform = platform;
this.translateService = translateService;
this.initialize();
}
private initialize(service: MyService): Promise<any> {
return service.doSomeAsync()
}
}
/* Spec */
describe('MyClass', () => {
let serviceMock: any;
let classUnderTest: MyClass;
beforeEach(() => {
classUnderTest = new MyClass(serviceMock);
);
describe('initialize', done => {
//initialize can also be protected and then I'll extend the class under test in the spec but this is the lazy approach.
classUnderTest['initialize']()
.then(() => {
//TEST ASYNC CONSTRUCTOR LOGIC
done();
});
});
} |
@stonelasley - I do the same as you. Did some research a while back and it seemed the best way. Also keen to improve if possible. |
@stonelasley Another way would be to use the lifecycle events of angular and ionic to decouple object creation and object initialization. In that case you could test the initialization method as you would test any method containing async calls. |
@euleule that's a good point and that's also an approach I've used. It points out a weakness in my example. I think I should have provided the initialize to the platform.ready callback. Nonetheless, I like your phrase "decouple object creation and initialization". |
@euleule / @stonelasley - would love a really quick example |
@lathonez If async things need to be done during instantiation, I try not to do them when the object is created, but when it is loaded for the first time. This way I have full control over what happens in the tests. Of course you could also supply a specialized class in the TestBed creation, that already mocks the service with default behaviour, so you can use it during object creation. class MyClass {
constructor(service: MyService) {
}
ngOnInit() {
this.initialize();
}
private initialize(): Promise<any> {
return this.service.doSomeAsync()
}
}
/* Spec */
describe('MyClass', () => {
let classUnderTest: MyClass;
beforeEach(() => {
let serviceMock: any = Mock.create(MyService);
serviceMock.doSomeAsync.and.returnValue(Promise.resolve());
classUnderTest = new MyClass(serviceMock);
});
describe('initialize', () => {
classUnderTest.ngOnInit();
expect(serviceMock.doSomeAsync).toHaveBeenCalled();
});
}; This example shows how I create a mock for a service that I want to call in a constructor. I added a second parameter to your TestUtils wich takes a list definitions that go to the provider definition. I use this to keep the dependencies in the test.ts as small as possible and only add global needed components and services. The dependencies for the tests are added in each respective test. This helps to avoid loading transitive dependencies, because of Mocks, that are written wrong and to me the tests appear a little more self-contained. describe("MyClass", () => {
beforeEach(async(() => {
let myServiceMock: MyService = <any>Mock.create(MyService);
myServiceMock.doSomeAsync.and.returnValue(Promise.resolve());
TestUtils.beforeEachCompiler([MyClass], [
{provide: MyService, useValue: pluginSettingsMock}
]).then((compiled) => {
fixture = compiled.fixture;
instance = compiled.instance;
fixture.detectChanges();
});
}));
...
}); The Mock object is a little helper I use to create jasmine Spys. |
@euleule - this is perfect, thanks.
I agree this is more correct.
^ That is really neat, thanks. |
@lathonez. I noticed when I run npm test from within a docker container, I get the following error: If I change the karma.conf.js from I no longer get the error. Not sure if this is a bug or if it was something wrong in my approach. Thanks for the great repo! |
@ibulmer - thanks for this. The entire test suite is actually run inside a docker container (by Circle). The docker image is here: https://hub.docker.com/r/lathonez/clicker/ Can you replicate on that image? If not, what are the differences between that and the image you are using? |
@lathonez I am running the docker image lathonez/clicker. First I Following this process I get the errors mentioned earlier If instead I run it with sh, download vim, edit the karma.conf.js, then run npm run test, it works. My commands are below.
I am guessing I need to run it with circle instead of manually? |
This is how it's run in circle: https://github.com/lathonez/clicker/blob/master/.circleci/config.yml#L27-L32 the |
Ah got it thanks! |
Hi @lathonez, I have posted my question on Stack. Here is link. https://stackoverflow.com/q/48758724/814477 Can anyone please help me ? |
The purpose of this issue is a sticky thread general for help with testing Ionic 2 projects.
E.g. you have our testing framework set up fine but you don't know how to test a particular scenario / component / feature, or you're getting unexpected results from some of your tests.
The correct place for posting such questions is stack overflow. Asking your question on stack will:
Please follow these guidelines:
Further issues raised on this repo will be referred here.
If you're having trouble setting up testing (e.g. you can't get a single basic test running against your app) please raise an issue here - don't use stack for that
The text was updated successfully, but these errors were encountered: