By Cliff Meyers
Most Single Page Applications (SPA) written in HTML and JavaScript interact with server side code using the familar XMLHttpRequest object. During development it can be convenient to run the application with mock data that eliminates this server dependency. This can be useful if the server side stack is complex and not easy to set up on a local machine or if a shared dev server running the server components suddenly goes offline. It’s also handy for tweaking the data returned by the services to ensure the UI behaves appropriately in specific scenarios. Naturally it’s imperative to integrate the SPA with real server code early and often but the flexibility provided by the “server mock” technique can be indispensible.
Note: while this article will illustrate how to mock services in an AngularJS application, this pattern applies to any UI technology (JavaScript or otherwise). The key is achieving Separation of Concerns (SoC) that allows real services and mock services to be easily swapped.
Let’s get started!
The Old Way: Use $http Directly
Angular provides the $http
and $resource
“services” for making HTTP calls to load data into your app. In tutorials and simple applications these are frequently injected directly into UI controllers:
https://gist.github.com/cliffmeyers/f19948b3ad760926d141
Here the controller invokes $http
directly and asks it to fetch data from a known URL. The same approach works for $resource
as well. While this approach is simple, it offers limited flexiblity and begins to overcomplicate the controller when data access becomes non-trivial.
Assume we have a number of UI widgets on this page that control the type of donuts we wish to load. When we invoke the backend service, we need to pass parameters to filter the donut based on size, filling, glaze and presence of a hole:
https://gist.github.com/cliffmeyers/8b673b37ae3b71dafb42
The code to construct the URL is getting more complex and muddying up the controller a bit. Furthermore if we have other views that need to fetch these donuts this code would need to be duplicated. Clearly we can improve the design through some refactoring and application of patterns.
The New Way: Use a Repository
This technique involves adding an intermediate layer between the controller and $http
that encapsulates data access and simplifies the code in the controller. Here’s a simple example of this expressed as an Angular module:
https://gist.github.com/cliffmeyers/eba60914a543028c359f
Note: I’m calling this intermediate a “Repository” although other terminology is likely valid, based on your preference. See “Quick Note on Names” below.
The Repository provides a very similar API to $http
in that it ultimately returns a Promise that is later resolved with the data returned by the server. However, it exposes a set of methods which provide a cleaner API to the controller rather than forcing it to perform string concatenation to build up URLs that are passed to $http
.
Using a Repository to Swap Out Mocks and Real Services
Now let’s explore how we can easily swap out real and mock services with another simple Angular module example:
https://gist.github.com/cliffmeyers/b25653d7fc54d00184ce
Now we have a new “mock” implementation that loads a JSON file from the local web server. We use Angular’s factory
method to control exactly what object is bound as donutRepository
for injection into the controller. Alternatively the mock implementation could simply create its own data programmatically and return a promise using the $q
and deferred
APIs:
https://gist.github.com/cliffmeyers/534c3326952498a65ee4
The configModel
referenced by the factory above is a simple object that holds configuration information about the application. The implementation below allows us to control the config options by passing parameters via the URL to the AngularJS app on startup:
https://gist.github.com/cliffmeyers/452fad76457ac22cc8a7
Accessing the application via ‘https://some.url/index.html#?useMocks=true will enable mock mode, based on the code above.
Once we push all data access code into its own discrete layer we can derive other benefits as well. We can easily centralize cross-cutting concerns such as logging or caching into our repository layer. If we need to implement offline mode in an application, each repository can collaborate with a service that queues up requests and pushes them to $http
once the application comes back online. This is vastly preferrable to managing this complexity in a controller.
Sample Application
I’ve built a very basic “Reddit Browser” AngularJS application that provides a working sample of these techniques. The code is available on Github here.
Clone the repo and then start the Node web server script using: ./scripts/web-server.js
The app will be available here:
‘https://localhost:8000/ng-repository/src/index.html’
“Mock mode” can be run easily via hitting ‘dev.html’ instead.
Feedback is encouraged. Drop me a comment below or hit me up on Twitter.
A Quick Note on Names
I pushed this section to the end because it’s just dealing with semantics. I chose “Repository” as the term for the the new data access layer but there are a variety of terms that are sensible. At the end of the day, the name has significance but the application of the pattern is what really matters. Here are a few other options:
- Proxy: because the intermediate sits between the client controller code and (ultimately) the backend server hosting the service. However, “Proxy” is an extremely generic pattern and doesn’t really tell us what it’s acting as a proxy to.
- Service: due to the popularity of the Service Oriented Architecture (SOA) buzzword, components residing on a server that return data in a HTTP response are frequently called “Services.” Therefore we could call the intermediate a Service. However, in the context of an AngularJS application this would be confusing since “service” is used generically to describe virtually any object available for dependency injection in the AngularJS context.
- Repository: made popular in Eric Evans’ book entitled Domain-Driven Design: Tackling Complexity in the Heart of Software, a Repository can be used in server side code to encapsulate querying and persistence, ultimately returning one or more Domain Objects. This aligns pretty closely with what’s going on in the AngularJS app so I decided to go with it.
- Data Access Object (DAO): this one is popular in Java circles. It’s probably at least as valid as Repository, perhaps moreso since it doesn’t carry along the Domain Model connotations.
It’s up to you. Pick what you like.
I posted an article with a similar idea, mocking out the server-side: https://craigwickesser.com/blog/2013/07/12/prototyping-with-a-server-in-the-browser/ Just thought I’d share. Thanks for sharing your perspective as well.
Hi, nicely written, I use a similar implementation.
IMHO no need to invent fancy names, this fits perfectly the “Delegation pattern” definition where execution is delegated to $http or $q etc. 🙂
https://en.wikipedia.org/wiki/Delegation_pattern
Nice stuff with getting rid those $http calls out of controllers. One thing that comes to my mind: I’m not sure if putting this “if” choosing between mock and regular implementation is the best approach. It works fine and is good way to cut off server dependencies. I wrote about the same topic here: https://michalostruszka.pl/blog/2013/05/27/easy-stubbing-out-http-in-angularjs-for-backend-less-frontend-development/ so you can take a look how I’d approach that.
Great article!
I suggest you use our open source spec helper for Angular testing https://github.com/kensho/ng-describe – saves all the boilerplate code.