Observations

Ionic app development & related technologies

Browser testing Ionic applications with Native Mocks

July 25, 2017, 9:00 am Categories:

Categories

One of the restrictions, if you will, of testing Ionic applications is the requirement of a handheld device or simulator where plugin functionality is concerned.

This can be especially frustrating when you want to test a small change to the codebase and have to wait upwards of 5 minutes for the application to be rebuilt from the command line and then published to the connected device.

With Ionic Native Mocks - a library of Mock plugins acting as placeholders for Native plugins - this restriction is, to some degree, lifted by being able to test Ionic applications (that implement Native plugin functionality) directly within the desktop browser.

This is particularly useful for the quick testing of projects although, as the name suggests, Ionic Native Mocks provide only placeholders and NOT the actual functionality of Native plugins themselves - that's why I state that the restriction is somewhat lifted. Although they emulate plugin behaviour they cannot and do not provide plugin functionality - they simply allow you to 'mock' the plugin behaviour so your code can be tested locally.

Currently the Native Mocks library is still under development and consists of mock plugins including:

  • actions-sheets
  • barcode-scanner
  • ble
  • bluetooth-serial
  • calendar
  • camera
  • contacts
  • date-picker
  • db-meter
  • device-motion
  • device-orientation
  • device
  • dialog
  • email-composer
  • geolocation
  • globalization
  • image-picker
  • keyboard
  • network
  • social-sharing
  • splash-screen
  • sqlite
  • status-bar
  • toast
  • touch-id
  • vibration

This will undoubtedly be added to over the coming weeks and months but be aware, that for now, there are certain Native plugins that aren't represented in the library.

Over the course of this tutorial we'll be exploring the use of the Geolocation Mock plugin to emulate the functionality of its native counterpart.

Laying the groundwork

From the Ionic CLI we begin by generating a new project, creatively titled ionic-mocks, with the following command:

ionic start ionic-mocks blank

Once created the next stage involves installing the Native plugin that we want to test along with its associated node package - in this instance the Geolocation plugin:

ionic cordova plugin add cordova-plugin-geolocation
npm install --save @ionic-native/geolocation

Following from this we then need to install the associated placeholder plugin from the Ionic Native Mocks library with the following command:

npm install --save @ionic-native-mocks/geolocation

IMPORTANT: When using the Ionic Native Mocks library you'll need to install both the Native plugin (and its associated node package) along with the corresponding mock plugin.

Rooting the application

With the necessary plugins and packages installed we now need to make some minor configurations to the application's root module - as displayed below:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { Geolocation } from '@ionic-native/geolocation';
import { GeolocationMock } from '@ionic-native-mocks/geolocation';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: Geolocation, useClass: GeolocationMock },
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Here we import both the Native and Mock Geolocation packages with the following:

import { Geolocation } from '@ionic-native/geolocation';
import { GeolocationMock } from '@ionic-native-mocks/geolocation';

Within the providers array we then need to ensure that the Geolocation plugin uses the GeolocationMock plugin class (allowing us to 'run' the plugin, so to speak, within our application):

{ provide: Geolocation, useClass: GeolocationMock }

Testing the Geolocation Mock plugin

With the root module configured to allow the Geolocation plugin to use the GeolocationMock we can begin testing the Mock plugin within the HomePage component.

Inside the ionic-mocks/src/pages/home/home.ts class import the Platform module and Geolocation plugins:

import { NavController, Platform } from 'ionic-angular';
import { Geolocation } from '@ionic-native/geolocation';

Within the class constructor we then initiate the Geolocation plugin and call its getCurrentPosition method like so:

constructor(  private platform  : Platform,
              public navCtrl    : NavController,
              public geoLoc     : Geolocation) 
{
    
   this.platform.ready()
   .then(() => 
   {
   
      this.geoLoc.getCurrentPosition()
      .then((resp : any) => 
      {
         console.dir(resp);
         console.log('Geolocation mocked!');
      })
      .catch((error : any) => 
      {
         console.log('Error getting location', error);
      });

   });
   
}

As you can see this simply prints console logs to the browser - nothing particularly impressive or useful, just a demonstration of how Mock plugins can be used to allow Ionic applications to be tested in a desktop browser.

Although minimal the code for the ionic-mocks/src/pages/home/home.ts class is covered in full below:

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { Geolocation } from '@ionic-native/geolocation';

@Component({
  selector    : 'page-home',
  templateUrl : 'home.html'
})
export class HomePage {

   
   constructor(  private platform  : Platform,
                 public navCtrl    : NavController,
                 public geoLoc     : Geolocation) 
   {
    
      this.platform.ready()
      .then(() => 
      {
   
         this.geoLoc.getCurrentPosition()
         .then((resp : any) => 
         {
            console.dir(resp);
            console.log('Geolocation mocked!');
         })
         .catch((error : any) => 
         {
            console.log('Error getting location', error);
         });

      });
    
   }



}

To test this works simply run the ionic serve utility from the Ionic CLI and, once the application runs in the browser, you'll see the following console logs being printed to the browser:

undefined
Geolocation mocked!

Hold on a second, what's with the value of undefined?

Well, by default, the methods used in Mock plugins simply resolve as promises and don't return any values which would explain why we see undefined being logged to the console.

According to the official documentation if Mock plugins are downloaded via Github and installed manually instead of using the node package manager the Mocks can be customised to return specific data.

This isn't something I have experimented with as yet (as I prefer to just test my applications on a handheld device) but that option is there if you need it.

Do remember

Ionic Mocks are designed to allow Native plugin functionality to be faked in the browser.

Don't forget to amend your code when testing the application on a handheld device/simulator by:

  • Removing the Mock plugins
  • Changing the root module providers array to use only the Native plugin

Thoughts

Native Mocks are an interesting approach to emulating Native plugin functionality in the desktop browser.

I'm not convinced though that there's a pressing need for this library due to the following reasons:

  • You cannot know your code is actually working as expected without testing on a native device - at best you are getting a vastly reduced facsimile of the experience which bypasses potential issues or errors that a Native plugin might throw up (I.e. with the Geolocation plugin there might be an issue with location accuracy that you would not be able to test with Native Mocks)
  • Browser testing is no substitute for device testing - see previous bullet point
  • I personally have no reservations about using a handheld device (even if the build and deployment process can be a little tedious to endure) for testing

That stated I think Native Mocks might be useful for developers who aren't quite confident yet with build processes and everything that can entail. Working within the browser then would definitely be more comfortable for novice Ionic developers and I could see the use of Native Mocks being applicable in that context.

I'll be interested to see how the project develops over the coming months, particularly with the addition of further mock plugins (such as Google Maps), and hopefully there'll be documentation for each plugin (as I could get the SQLite Native Mock to run the create method but not the executeSQL method even while scanning through the source code of the SQLite Mock - whether that's developer error on my part [more than likely] or an issue with the Mock I can't tell at this time).

In summary

As you can see this tutorial demonstrates a very simple (although, admittedly, not particularly useful) example of how Native Mocks can be used to emulate plugin functionality when browser testing your Ionic applications.

I'll cover further testing approaches for Ionic in forthcoming tutorials but I hope, for now at least, this tutorial has given you some idea of how it's possible to test Ionic Native plugins within a desktop browser.

Feel free to let me know what your thoughts and reactions are to this tutorial by leaving your comments in the form below.

If you enjoyed what you've read here then please consider signing up to my mailing list and, if you haven't done so already, take a look at my e-book - Mastering Ionic : Building a Real World Application for further information about testing Ionic applications.

Tags

Categories

Leave a comment

Feel free to share your thoughts, opinions and/or suggestions with regards to this blog article.

There's only one rule: Be nice - trolling others, behaving abusively or spamming the blog will result in your post being deleted.

Top