Rapidly Building Mock API Servers for Testing and Development
On my most recent project I was building the client-side of a mobile app. I was a few days ahead of the backend in terms of functionality, but what was really giving me issue was the absence of any kind of test data. Rather than kill my momentum and allow the backend to block my development, I decided to build a quick API “emulator” that would allow the client to perform actions and feed it randomized test data.
Motivation
I needed to build this server FAST. Adding a new api call needed to require a minimum amount of effort, and to build as quickly as possible I needed to use something that I was familiar with. Since I enjoy python for web I used bottle, a microframework for python. Another thing that I knew was that I did not need to keep track of any data on the backend. I could just feed the client hardcoded or randomized data. This eliminated the need to define models and setup a database.
Starting out… we just needed to be able to login.
[code language=”python”]
#!/usr/bin/env python
from bottle import get, post, request, run
from hashlib import sha1
from random import randint as rand, choice
import json
@post(‘/login’)
def login():
username = request.forms.get(‘username’) or ‘default_username’
print ‘%s logged in!’ % (username)
return json.dumps({‘status’: ‘OK’, ‘session_token’: sha1(username).hexdigest()})
if __name__==’__main__’:
run(host=’0.0.0.0′, port=8080, reloader=True)
[/code]
Test it out yourself…
[code]
% curl -X POST http://127.0.0.1:8080/login -d username=ryan
{"status": "OK", "session_token": 2497}
[/code]
Alright, now the app logs in, but it requests a friends list… lets build that as fast as possible…
[code language=”python”]
def rand_friend(num):
return {‘name’: ‘Friend %d’ % (num),
‘age’: rand(18,30),
‘location’: choice([‘USA’, ‘UK’, ‘JP’, ‘KR’]),
‘twitter’: ‘@friend%d’ % (num)
}
@get(‘/friends’)
def friends():
return json.dumps({‘status’: ‘OK’,
‘friends’: [ rand_friend(x) for x in range(rand(5,20)) ]
})
[/code]
Building an API emulator in such a manner took under an hour and allowed my progress to continue and not be blocked by the backend team. It is still used in testing.
Next steps?
From here you can add any calls that you need extremely quickly with minimal effort. Once you get further into development you could start using the requests library to proxy working calls to the dev/staging server while still providing your own methods for feeding in test data. You could even add in an ORM and database for some reproducible test data and fake interactions such as chatting.
Other mentions
I picked bottle because I like python and knew I could build out a mock api quickly with it. There are tons of microframeworks across many languages. Rubists can use Sinatra, node.js folks can use express, the list goes on and on!