Skip to content
This repository has been archived by the owner on Jul 14, 2022. It is now read-only.

Mock mode

wwitman edited this page Dec 16, 2014 · 14 revisions

Running Apigee-127 in mock mode

The handy and convenient Apigee-127 mock mode lets you "mock up" API routes/paths and response objects in the Swagger editor and test them without writing any controller code. By default, mock mode responses are system-generated; however, you can optionally implement custom mock controllers to return custom responses.

When to use mock mode

Mock mode is useful when you are designing your API model in the Swagger editor, but you're not ready to implement the API's handler/controllers. For example, you might use mock mode when you're trying to decide which API routes you need and what kind of data each API operation should return. Basically, mock mode let's you perfect your API design without writing any Node.js code.

When you're happy with the overall API design, then you can wire up and implement the API's controller/handlers.

Starting a project in mock mode

To start an Apigee-127 project in mock mode, use the -m flag:

a127 project start -m

Quick example: mock mode in action

Here's a simple example where the API definition only has one path (/weather) and a response object called WeatherResponse. In this case, the WeatherResponse object returns a simple message of type string. Here's the Swagger YAML:

        swagger: '2.0'
        info:
          version: "0.0.1"
          title: Mock mode test
        host: localhost
        basePath: /
        schemes:
          - http
        consumes:
          - application/json
        produces:
          - application/json
        x-a127-services: {}
        paths:
          /weather:
            get:
              responses:
                "200":
                  description: Success
                  schema:
                    $ref: #/definitions/WeatherResponse
        definitions:
          WeatherResponse:
            required:
              - message
            properties:
              message:
                type: string

To test this API configuration in mock mode, start Apigee-127 with the mock mode "-m" flag:

a127 project start -m

When you call the API, like this:

curl -i http://localhost:10010/weather

Mock mode returns this system-generated response:

    {
    "message": "Sample text"
    }

If you change the response object to return an integer...

        WeatherResponse:
            required:
                - message
            properties:
                message:
                type: integer

The mock response is an integer:

    {
    "message": 1
    }

Building and testing your API model in mock mode

An actual weather API isn't only going to return a string; it's going to return a more complex response object consisting of objects, strings, and numbers. As you build your API, you can model and test the intended behavior entirely in mock mode.

For example, here's the WeatherResponse object from the weather-basic sample on GitHub. It's got strings, numbers, arrays, and objects representing various aspects of weather data.

       WeatherResponse:
        properties: 
          base: 
            type: "string"
          clouds: 
            type: "object"
            properties: 
              all: 
                type: "number"
          cod: 
            type: "number"
          coord: 
            type: "object"
            properties: 
              lat: 
                type: "number"
              lon: 
                type: "number"
          dt: 
            type: "number"
          id: 
            type: "number"
          main: 
            type: "object"
            properties: 
              humidity: 
                type: "number"
              pressure: 
                type: "number"
              temp_max: 
                type: "number"
              temp_min: 
                type: "number"
              temp: 
                type: "number"
          name: 
            type: "string"
          sys: 
            type: "object"
            properties: 
              country: 
                type: "string"
              id: 
                type: "number"
              message: 
                type: "number"
              sunrise: 
                type: "number"
              sunset: 
                type: "number"
              type: 
                type: "number"
          weather: 
            type: "array"
            items: 
              type: "object"
              properties: 
                description: 
                  type: "string"
                icon: 
                  type: "string"
                id: 
                  type: "number"
                main: 
                  type: "string"
          wind: 
            type: "object"
            properties: 
              deg: 
                type: "number"
              speed: 
                type: "number"

If you call this API in mock mode, it returns the following JSON. Objects, arrays, strings, and numbers are all "mocked up" with mock values of the appropriate data type:

    {
        "base": "Sample text",
        "clouds": {
            "all": 1
        },
        "cod": 1,
        "coord": {
            "lat": 1,
            "lon": 1
        },
        "dt": 1,
        "id": 1,
        "main": {
            "humidity": 1,
            "pressure": 1,
            "temp": 1,
            "temp_max": 1,
            "temp_min": 1
        },
        "name": "Sample text",
        "sys": {
            "country": "Sample text",
            "id": 1,
            "message": 1,
            "sunrise": 1,
            "sunset": 1,
            "type": 1
        },
        "weather": [
            {
                "description": "Sample text",
                "icon": "Sample text",
                "id": 1,
                "main": "Sample text"
            }
        ],
        "wind": {
            "deg": 1,
            "speed": 1
        }
    }

Implementing mock mode controllers

By default, mock mode returns programmed responses, like "Sample text" for a string, a number for an integer, and so on.

But you can also create mock controllers with handler methods that return custom responses.

Place these custom "mock" controllers in the /api/mock directory.

Here's an example from the Apigee-127 example-project. It's a mock controller that returns some data whenever the search() handler method is called:

    'use strict';

    module.exports = {
      search: search
    };

    function search(req, res, next) {

      res.json([{ user: 'mock', created: new Date(), text: 'this'}]);
    }

###Wiring up and implementing the API controller

After you're happy with your API design, you're ready to implement wire up the controller for the /weather path.

You simply specify in the Swagger spec the route handler (controller) file, which method to call in the controller (operationId), and any query parameters you wish to pass:

In weather sample's swagger.yaml file, it looks like this:

      paths:
          /weather:
            x-swagger-router-controller: weather
            get:
              description: "Returns current weather in the specified city to the caller"
              operationId: getWeatherByCity
              parameters:
                - name: city
                  in: query
                  description: "The city you want weather for in the form city,state,country"
                  required: true
                  type: "string"

Finally, implement the route's operation -- the getWeatherByCity() method in api/controllers/weather.js -- which calls the back-end service and returns the response.

Here is the sample controller implementation for the weather-basic sample:

'use strict';

var util = require('util');
var request = require('request');

module.exports = {
  getWeatherByCity: getWeatherByCity
}

function getWeatherByCity(req, res) {
  var city = req.swagger.params.city.value;
  var url = "http://api.openweathermap.org/data/2.5/weather?q="+city+"&units=imperial";
  console.log('Executing request: '+url);
  request.get(url).pipe(res);
  };

In the case of this sample weather API, the controller calls the back-end service (the OpenWeatherMap API). When you call the API like this:

curl http://localhost:10010/weather?city=Boulder,CO

The same response object that you previously modeled and tested in mock mode is filled in with the correct values:

    {
        "base": "cmc stations",
        "clouds": {
            "all": 40
        },
        "cod": 200,
        "coord": {
            "lat": 40.02,
            "lon": -105.28
        },
        "dt": 1411077635,
        "id": 5574991,
        "main": {
            "humidity": 27,
            "pressure": 1016,
            "temp": 87.62,
            "temp_max": 91.99,
            "temp_min": 80.01
        },
        "name": "",
        "sys": {
            "country": "United States of America",
            "id": 538,
            "message": 0.0175,
            "sunrise": 1411044334,
            "sunset": 1411088663,
            "type": 1
        },
        "weather": [
            {
                "description": "scattered clouds",
                "icon": "03d",
                "id": 802,
                "main": "Clouds"
            }
        ],
        "wind": {
            "deg": 160,
            "speed": 7.78
        }
    }
Clone this wiki locally