Fake it as you make it: why fake services are awesome for developers Dwolla Follow Jan 25, 2016 · 6 min read

This blog post comes from Shea Daniels, a developer at Dwolla. When Shea isn’t busy building awesome new things, you can usually find him out for a run.

It’s often said in life that we “stand on the shoulders of giants.” This rings especially true now that we’re in an era of abundant open source software and SaaS providers.

Now, more than ever, we build applications by relying on tools and services that others have made. This may even be standard practice inside your own organization as other teams deliver functionality through a microservices architecture.

Building software by composing services is extremely powerful, but it can still be a rocky road. Several factors can make it difficult to write and test your code:

Complex scenarios may not be easy to test with real data

Running elaborate business logic may consume resources

Sandbox environments may not exist for 3rd party APIs

Just fake it

So what can be done to mitigate these issues? The answer is to fake it while you’re making it!

You can see this in everyday life. Whenever the real thing is too expensive or impractical, we sub it out with something fake as a stand in — think movie props or mannequins for tailors. This is also a fairly common engineering practice; my favorite examples are the boilerplate capsules used to evaluate rockets and other space hardware.

In the software world, if you practice TDD you should be familiar with the use of test doubles (mocks, fakes, and stubs) for dependencies in your unit testing code. Used instead of the real implementations of objects, fake dependencies isolate the code under test by providing predictable results given certain input. This isolation is useful for tracking down issues and fully exercising your code without complicated setup.

The same concept can be applied when developing an integration with a third party service. By building a fake copy of the web service, you gain the same advantages of isolation and repeatability as you test your application. This is especially useful if the service you’re depending on is being developed in tandem and has yet to be fully implemented.

There are some existing tools for quickly standing up your own fake services, such as Nock and Frock. But with Node.js and a few NPM packages, it’s easy enough to build your own from scratch.

In this post we’ll include:

An actual example

How to get started

Possible scenarios

Some of the downsides

A real example

Let’s break down a real example that Dwolla has recently open sourced: Nodlee. You can see it in action by checking out our instant bank account verification demo — here it’s used as a backing service.

Getting started

Nodlee is a simple web server written in Javascript and run via Node.js. It depends on the following NPM packages, which you can see in the package.json file:

express — web framework

body-parser — body parsing middleware

node-cache — caching module

minimist — argument parser library

If you haven’t used Node or express before, there are a ton of great tutorials, or you can read through the Nodlee source code to get a feel for it. The readme has a lot of great info and the code entry point is app.js.

Responses

The first thing to do when building out a fake service is to look at the documentation for the real API and experiment with the service to discover how it works. With that knowledge, you can figure out which endpoints need to be mocked and what the responses should look like.

For a simple example, here’s the Nodlee health check endpoint response: health.js

module.exports = function (req, res) {

res.json({ healthy: true });

};

These responses can be as simple or as complicated as needed.

If returning the same canned response every time isn’t enough, consider scanning the request for sentinel values that you define. Then you can use those values to decide which data to send back. You can even use a templating language like Handlebars for generating your responses if you want to get swanky.

Complex scenarios

For the instant account verification product we were building, even sentinel values and templating weren’t quite enough. We found that we were constantly editing multiple files in the fake service code to set up complex scenarios.

The first step to making this easier was to consolidate all of the possibilities that determined a particular scenario into a single list of options in the code: scenario.js

module.exports = function Scenario() {



this.contentServiceId = 0;

this.isMfa = true;

this.mfaTimeout = false;

this.mfaPass = true;

this.mfaTypes = ['q'];

this.refreshesSet = 1;

this.refreshesLeft = 1;

this.errorType = 0;

this.accounts = [

{

routingNumber: '222222226',

accountNumber: '5031123001',

accountType: 'CHECKING',

accountHolder: 'John Wayne',

accountName: 'Your Account #1',

balance: '1000'

}];

}

This object can then be checked in all of the service endpoints in order to determine the appropriate response. With this in place, developers could set up the flow to behave however they wanted just by editing this single file.

Sentinel values on steroids

We have local development covered now, but what about testing in sandbox environments where we can’t edit the fake service code? Not only that, but what if we wanted coverage of our flow with automated UI tests (e.g. Robot Framework)?

What we need now is a service with a memory longer than a single web request and a way for automated tests to trigger whatever scenario is needed. This is where the minimist and node-cache NPM packages come into play.

With minimist, we are able to take certain inputs in a web request and treat them as if they were command line interface options. Those options can then be translated into order to set the properties of the Scenario object we’ve just discussed:

var scenarioData = optionsParser.parse(req.body.someInput)

optionsParser.js

exports.parse = function(options) {



var data = new Scenario();



if (options.indexOf("-") < 0) {

return data;

}



var args = parseArgs(options.split(' '));



if (args['nomfa'])

data.isMfa = false;



...



return data;

}

Now that we have the options set for the scenario we want, we use node-cache to persist it across web requests: scenarioManager.js

var cache = new NodeCache({ stdTTL: 900, checkperiod: 300 });



exports.set = function(...) {



...



cache.set(userSessionToken, scenarioData);

return scenarioData;

};

Now we can use the cache to access the scenario that’s currently being tested at any point we need to build a response: getMfaResponse.js:

module.exports = function(req, res) {



scenarioManager.get(req.body.userSessionToken, function(scenarioData) {



if (!scenarioData.mfaTypes) {

...

} else if (scenarioData.mfaTypes.length < 1) {

...

} else {

...

}

});

};

The downsides

As with anything, fake services are not a silver bullet. There are a few caveats to keep in mind:

Are you sure you understand the real service well enough to build a fake version of it?

Watch for edge cases where you may not be duplicating the behavior of the real service

If you do find edge cases, be sure to cover them with appropriate tests; manual testing with your fake service is not a replacement for good test coverage with unit/integration tests

Plan for regular maintenance of your fake to keep up with any changes in the interface or behavior of the API you depend on

Using a fake does not relieve you from the task of running your code against the genuine article

The last bullet point is important since there’s a large difference between “should work” and “actually works.” At some point in your workflow you’ll need to test the full production stack!

Conclusion

Here at Dwolla we’re committed to making developers’ lives easier by providing a great API for moving money with ACH transfers.

We’ve found the concept of fake services to be invaluable in making this happen. If you found this useful, please share this article and comment with your own experiences. Happy building!