I am working on a new project which will query data from a 3rd party REST API. This is for a real time sports data feed, so the feed only works when a game is actually taking place.
Although the 3rd party provides good documentation (XSD, etc), they have no way to simulate a game happening, and so to test code I have written against this API I would have to wait for an actual game to be happening.
My only recourse is to write code to simulate a game on my own, but it seems like a lot of work. How would you approach this?
2
This is the perfect use case for a mock object. There are mocking libraries for every popular language. You would want to mock the object that provides the REST service responses to return test data. You can either hand-generate the test data or collect it from previous calls to the live system.
2
Wait until a game is happening. Capture every event from the feed. Write a simulator that replays the events at the appropriate times. Voila, you have a feed simulator with real data.
1
I recommend writing your own simulator. You can use it to test all sorts of scenarios;
- Server accepts connection but doesn’t respond
- Server times out
- Server send back garbage reply
etc…
When I’ve done this in the past, I’ve used “special” values in the request messages to prompt the simulator to do what I need. This also makes it possible to run end-to-end tests without going outside your development environment.
Edit: For example, if your project submits XML to a 3rd party service, the request might include e.g. <value>50.00</value>
. The simulator can be coded (or, better, configured) so that 50.00 => explode, 60.00 => garbage, 70.00 => close connection, and so on. The idea is that the behaviour of the simulator depends on its input, which you control in each test case.
2
Considering that probably the bookmaker provides some sample data (and this can be saved during the integration phase), my advice is to organize those feeds in this way:
- List of events
- Updates for scheduled events
- Odds updates
- Results
Probably the provider offers 2 types of updates: Push (POST) and Pull (GET).
At this point you should
- Create a simple server that just handles GET requests, so that your programmers can elaborate algorithms.
- Create an automation to manage submissions of the same information and can thus stressing your system.
Manage the development and testing
Without going into the details of technology to be used, you get a mini-server, which responds only to 4 URLs (or those necessary depending on what the provider offers), and a mini-push service.
A very good thing to keep in mind when working with the “mini-server”, are the handlers of the HTTP protocol. Create a server on port 80 is very simple, and solves the problem. You have to be sure to inject all the information in the responses GET as the provider makes (this will avoid problems when put into production).
Personally I would do a simple Perl server or the same but with Nodejs. With regard to the injection of data, will be sufficient a timer, which invokes an offline browser (CURL, WGET)
I simulated REST API by using combination of cucumberjs, phantomjs with setting proxy server to 127.0.0.1 and hooking a node.js process with http-proxy
and nock
there. CucumberJS is not the important part, you can write test scenario any way, the rest is the key to the simulation. It is able to mock simply by match-request-return-data, but you can as well filter by patterns and hook callback function to produce a reply, so you can simulate to any level of granularity that you need (in extreme ending with a full demo server, but you can do it incrementally).
It works nicely:
- Phantomjs request an URI.
- Request goes to proxy server on 127.0.0.1:port.
- Your node.js process proxies it transparently forward using
http-proxy
. So any “normal” loading (pages, images) works. - If you choose to intercept some requests (API, mainly) you use
nock
for it.
In my scenario, I combined it with cucumber js tests in the same process, so it went as:
- Test runs.
- It sets up
nock
HTTP mocking for scenario it tests. - It loads a page in phantomjs via Selenium protocol.
The rest is as shown earlier in this paragraph (that is, it is a bit of a cycle, I as test runner instruct phantomjs to load a page, which forward all requests back to me, and I forward them to the net; or intercept them if it is the tested API).