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

Mock mode

wwitman edited this page Sep 19, 2014 · 14 revisions

Modeling an API in mock mode

The handy and convenient Apigee 127 mock mode lets you "mock up" API paths and response objects in the Swagger editor and test them without writing any controller code.

  • Running in mock mode
  • Quick example
  • Building and testing an API in mock mode
  • Wiring up and implementing the API controller

When to use mock mode

Use mock mode when you're designing your API's paths and response objects in the Swagger editor. Basically, mock mode let's you perfect your API design without writing any Node.js code.

When you're happy with the API design and the shape of the response object schemas, then you can wire up and implement the API's controller/handlers.

Running in mock mode

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

a127 project start -m

Quick Example

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:

```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-volos-resources: {}
    paths:
      /weather:
        get:
          responses:
            "200":
              description: Success
              schema:
                $ref: WeatherResponse
    definitions:
      WeatherResponse:
        required:
          - message
        properties:
          message:
            type: string
```

To test this configuration in mock mode, start Apigee 127 in mock mode flag:

a127 project start -m

When you call the API, like this:

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

Mock mode returns this response:

    {
    "message": "Sample text"
    }

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

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

The mock response is an integer:

    {
    "message": 1
    }

Building and testing your API model in mock mode

The actual weather API isn't only going to return a string, it's actually 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.

```yaml
   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
        }
    }

###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 backend 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:

```json
{
    "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