Blog

Mock Your Ajax Requests with Mockjax for Rapid Development

Most backend developers are familiar with the concepts of mocking objects or stubbing in methods for unit testing. For those not familiar with mocking, it’s the simulation of an interface or API for testing or integration development purposes. Mocking with front-end development though is still quite new.

Much of the development that appendTo does focuses on front-end development tied to RESTFUL web services. As such we’re able to spec out the service contract and data format at the beginning of a project and develop the front-end interface against mock data while the back end team builds the production services.

I originally developed this plugin for appendTo back in March of this year and our team has been using it in all of our projects since. appendTo is committed to sharing our tools and best practices with the community so it’s with much excitement that we’re releasing this plugin. (A sneak peek was available to the Silicon Valley JavaScript Users Group and those that attended our OSCON tutorial)

Plugin Overview

Abstract: The mockjax plugin is a development and testing tool for intercepting and simulating ajax requests made with jQuery with a minimal impact on changes to production code.

Overview: Your First Mock

Our first example will be for a simple REST service for a fortune app with the REST endpoint being /restful/fortune which returns the following JSON message:

{ "status": "success",
  "fortune" : "Are you a turtle?"
}

To pull the fortune into our page, we’d use the following HTML & jQuery code:

<!DOCTYPE html>
<html>
  <head>
    <title>Fortune App</title>
    <script src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
  </head>
<body>
  <div id="fortune"></div>
</body>
</html>
$.getJSON('/restful/fortune', function(response) {
  if ( response.status == 'success') {
    $('#fortune').html( 'Your fortune is: ' + response.fortune );
  } else {
    $('#fortune').html( 'Things do not look good, no fortune was told' );
  }
});

At this point if we were to run this code it would fail since the REST service has yet to be implemented. This is where the benefit of the Mockjax Plugin starts to pay off. The first step in using Mockjax is to include the Plugin (you can grab the latest source from github) Once you have that included, you can start intercepting Ajax requests and mocking the responses. So let’s mock out the service by including the following code:

$.mockjax({
  url: '/restful/fortune',
  responseTime: 750,
  responseText: {
    status: 'success',
    fortune: 'Are you a turtle?'
  }
});

Defining a JOSN string inline requires a JSON.stringify method to be available. For some browsers you may need to include json2.js

What the plugin does at this point is replace the $.ajax method with a wrapper that transparently checks the URL being requested. If the URL matches one defined by $.mockjax(), the plugin intercepts the request and sets up a mock XMLHttpRequest object before executing the jQuery.ajax handler. Otherwise, the request is handed back to the native $.ajax method for normal execution. One benefit in this implementation detail is by simulating the XMLHttpRequest object, the plugin continues to make use of jQuery’s native ajax handling.

As you write code to mock responses, there’s great value in there are no modifications required to production code. The mocks can be transparently inserted. This provides easy integration into most frameworks by including the plugin and mock definitions through your build framework. It’s also possible to include it at run time by listening for a flag query string flag and injecting the plugin and definitions.

Mockjax in Depth

Now let’s look at the various approaches to defining mocks as offered by the plugin. The sections below feature an extensive overview of the flexibility in Mockjax and creating responses.

Data Types Available for Mocking

jQuery is able to handle and parse Text, HTML, JSON, JSONP, Script and XML data formats and Mockjax is able to mock any of those formats. Two things to note, depending upon how you Mock out JSON and JSONP you may need to include json2.js for the JSON.stringify() method. Additionally if you mock XML inline, you’ll need to include the xmlDOM plugin that transforms a string of XML into a DOM object. If you use the proxy approach outlined below, there’s no need to include either the JSON or XMLDOM plugins.

Step 1. Define the URL

The first thing you need to do when mocking a request is define the URL end-point to intercept and mock. As with our example above this can be a simple string:

$.mockjax({
  url: '/url/to/rest-service'
});

or contain a * as a wildcard:

$.mockjax({
  // Matches /data/quote, /data/tweet etc.
  url: '/data/*'
});

or a full regular expression:

$.mockjax({
  // Matches /data/quote, /data/tweet but not /data/quotes
  url: /^/data/(quote|tweet)$/i
});

Step 2. Define the Response

The second step is to define the type of response. The two main properties you’ll be dealing with are either responseText or responseXML. These properties mirror the native XMLHttpRequest object properties that are set during a live response. There are three different patterns for specifying the responses: Inline, Proxy, and Callback.

Inline Responses

A simple text response would be:

$.mockjax({
  url: '/restful/api',
  responseText: 'A text response from the server'
});

A simple XML response would be:

$.mockjax({
  url: '/restful/api',
  // Need to include the xmlDOM plugin to have this translated into a DOM
  responseXML: '<document><quote>Hello world!</quote></document>'
});

As you can quickly see, if you have a significant amount of data being mocked this becomes unwieldy. So that brings us to the next pattern of proxying.

Proxy

In this example below, the Mockjax plugin will intercept requests for /restful/api and redirect them to /mocks/data.json.

$.mockjax({
  url: '/restful/api',
  proxy: '/mocks/data.json'
});

Callback

In the final response pattern, we can define a callback on the response property and have it set responseText or responseXML as needed.

$.mockjax({
  url: '/restful/api',
  response: function() {
    this.responseText = 'Hello world!';
  }
});

Advanced Mocking Techniques

At this point we’ve looked at a series of basic mocking techniques with Mockjax and will now unpack some of the additional functionality contained in the plugin.

Simulating Response Time and Latency

Simulating network and server latency for a mock is as simple as adding a responseTime property to your mock definition:

$.mockjax({
  url: '/restful/api',
  // Simulate a network latency of 750ms
  responseTime: 750,
  responseText: 'A text response from the server'
});

Simulating HTTP Response Statuses

It’s also possible to simulate response statuses other than 200 (default for Mockjax) by simply adding a status property.

$.mockjax({
  url: '/restful/api',
  // Server 500 error occurred
  status: 500,
  responseTime: 750,
  responseText: 'A text response from the server'
});

Setting the Content-Type

You can set the content type to associate with the mock response, in the example below, we’re setting a json content type.

$.mockjax({
  url: '/restful/api',
  contentType: 'text/json',
  responseText: {
    hello: 'World!'
  }
});

Setting Additional HTTP Response Headers

Additional HTTP Response Headers may be provided by setting a key in the headers object literal:

$.mockjax({
  url: '/restful/api',
  contentType: 'text/json',
  responseText: {
    hello: 'World!'
  },
  headers: {
    etag: 'xyz123'
  }
});

Force Simulation of Server Timeouts

Because of the way Mockjax was implemented, it takes advantage of jQuery’s internal timeout handling for requests. But if you’d like to force a timeout for a request you can do so by setting the isTimeout property to true:

$.mockjax({
  url: '/restful/api',
  isTimeout: true
});

Dynamically Generating Mock Definitions

In some situations, all of your REST calls are based upon a URL schema. Mockjax has the ability for you to specify a callback function that is handed the $.ajax request settings. The callback function may then either return false to allow the request to be handled natively, or return an object literal with relevant Mockjax parameters set. Below is an example that rewrites all Ajax requests to proxy to static mocks:

$.mockjax(function(settings) {
  // settings.url == '/restful/<service>'
  var service = settings.url.match(//restful/(.*)$/);
  if ( service ) {
    return {
      proxy: '/mocks/' + service[1] + '.json'
    };
  }
  return;
});

Dynamically Generating Mock Responses

It’s also possible to dynamically generate the response text upon each request by implementing a callback function on the response parameter:

$.mockjax({
  url: '/restful/webservice',
  dataType: 'json',
  response: function(settings) {
    this.responseText = { say: 'random ' + Math.random() };
  }
});

Globally Defining Mockjax Settings

It’s also possible to define the global defaults for all Mockjax requests by overwriting the $.mockjaxSettings object. By default the settings are as follows:

$.mockjaxSettings = {
  status:        200,
  responseTime:  500,
  isTimeout:     false,
  contentType:   'text/plain',
  response:      '',
  responseText:  '',
  responseXML:   '',
  proxy:         '',
  lastModified:  null,
  etag:          ''
};

To overwrite a particular settings such as the default content-type, you would do the following:

$.mockjaxSettings.contentType = 'text/json';

Removing Mockjax Handlers

Remove all mockjax handlers:

$.mockjaxClear();

Remove Single Mockjax Handler

var id = $.mockjax({
   ...
});
$.mockjaxClear(id);

Conclusion

So there you have it, Mockjax unpacked! There are a number of additional posts in the pipeline surrounding this topic and how to apply and integrate it with your project. So stay tuned! In the meantime, the plugin code is readily available on github and feel free to report any issues you find in the plugin’s github issue tracker. Enjoy!

Tweet about this on TwitterShare on FacebookShare on RedditShare on Google+Share on LinkedIn

  • Pingback: Tweets that mention Mock Your Ajax Requests with Mockjax for Rapid Development | Enterprise jQuery -- Topsy.com

  • Pingback: Twitted by milosm

  • Pingback: Twitted by datafok

  • Pingback: Mock Your Ajax Requests with Mockjax for Rapid Development | Enterprise jQuery « Netcrema – creme de la social news via digg + delicious + stumpleupon + reddit

  • https://me.yahoo.com/noelbossart#a81bf Noel

    Hello! Cool post! Is it possible to simply return the content of a local file but with a responseTime? This looks pretty promising!

  • Pingback: Mock Your Ajax Requests with Mockjax for Rapid Development | Enterprise jQuery : Popular Links : eConsultant

  • http://www.facebook.com/ianmassey Ian Massey

    Awesomely useful. Especially like the ability to test lots of different scenarios, no response, bad response, etc without having to fake it server side. Will definitely be using this in my next project! Thanks for sharing.

  • jdsharp

    Hi Noel,

    Great suggestion! I'll see what I can do to add this.

  • Pomeh13

    What a nice post ! I love this kind of stuff, I'll use it for sure. The ability to intercept the AJAX calls and returns local objects is very useful when you want to test your application. But I have few questions. Is it possible to pass functions as properties to the $.mockjax method ?

    Instead of :

    $.mockjax({
    url: '/restful/api',
    responseTime: 750,
    responseText: 'A text response from the server',
    status: 200,
    isTimeout: false,
    contentType: 'text/plain',
    });

    could we do something like :

    $.mockjax({
    url: '/restful/api',
    responseTime: function() {
    if( somecondition )
    return 100;
    else
    return 750;
    },
    responseText: 'A text response from the server',
    status: function () {
    return [200, 404, 500][ Math.floor(Math.random()*3) ];
    },
    isTimeout: false,
    contentType: 'text/plain',
    });

    I don't know why we could return a random status, but if we have to, it would be nice to be abble to ! :)

    And second question, how can we have access to the request parameter ? Let's imagine you have a form tag, with a username and a password field. You bind an handler to the submit event of the form, this handler serialize your form and send it via AJAX and a POST call. This call use to return the username the user just type, or the string 'bad.login' for example. Then, in the mockjax object, can we configure the response method to return the username the user juste typed in ? If we have an argument to the response method which represents the current request it could be easy to return a pre-configured response, depending on each request. I'm not sure to explain it nice, my english is very terrible =(

    Anyway, I like the idea of this plugin, and I'm grateful that you have shared it with us (and sorry again for my english!)

  • http://twitter.com/2dc Anthony Heukmes

    Hi,

    This is very interesting, thanks for your work.
    I'm planning to integrate this library with Choco : http://github.com/ahe/choco

    Are you planning to support HTTP verbs?

    For example, if I send a GET request to /posts I'm expecting an array of posts in response. But if I send a POST request to /posts, I'm expecting to receive a JSON representation of the newly created post. Is it possible to do that?

    Cheers!

  • Pingback: Eric Blue’s Blog » Weekly Lifestream for July 25th

  • jdsharp

    Hi Pomeh13,

    To answer your first question, it is possible to modify the responseTime. (Though it takes a bit of code. I'll post an update to github shortly that will make it much easier and will reply to this comment.) See the section “Dynamically Generating Mock Definitions”.

    For your second question, the answer is yes :)

    $.mockjax({
    url: '/restful/webservice',
    dataType: 'json',
    response: function(settings) {
    this.responseText = { user: settings.data.username };
    }
    });

    $.ajax({

    data: {
    username: $('#someinput').val()
    }

    });

    Cheers!
    - Jonathan

  • Justinbmeyer

    Have you guys looked at JMVC's fixtures? It does the same thing by overwriting $.ajax so it takes an additional fixture param. This means your code still works if you drop the fixture script.

  • jdsharp

    Hi Justin,

    Thanks for your comment! I did come across the fixtures plugin back in June. While there are a few similarities between mockjax and fixtures, there's a fundamental difference in the approach that mockjax has taken. Mockjax is designed to overlay the production codebase, whereas fixtures is integrated within it. (Even though you can simply remove the fixtures plugin for production, you still have “fixtures:” attributes as part of the production code.) Mockjax takes an approach that provides for a Separation of Concerns which we feel is a core concern in enterprise development. Production code is never modified to introduce a mocking or test environment which is important from an integration standpoint. So while there are some surface level similarities, there's a fundamental difference in approach that the Mockjax plugin took.

    Cheers,
    - Jonathan

  • ChrisRaven

    Hi,

    Is there any way to check, what was the query string passed to the original AJAX? I would like to not only test the response, but also arguments passed to server.

    Best regards,
    ChrisRaven

  • wwwhack

    I'll second ChrisRaven's point. I'm using a plugin (DataTables) that requires an echo parameter be returned from the server with the same value. Access to the query string would be important for this sort of thing.

  • jdsharp

    Hi Chris,

    There is! Here's a gist that shows how: http://gist.github.com/615972

    Essentially you plugin in data: {} for mockjax to inspect against. It'll do deep inspection.

    Cheers,
    - Jonathan

  • jdsharp

    I just replied to Chris' comment. (here's the gist http://gist.github.com/615972)

  • ChrisRaven

    Hi,

    Thanks for your response.
    Currently I'm doing ajax tests without Mockjax, but it is good to know, if I'll find, that my method is not enough.

    Here is my current method, if someone need simple ajax testing:

    test('ajax', function () {
    var ajaxOptions;
    $.ajax = function (param) {
    ajaxOptions = param;
    };
    myAjaxFunction();
    ajaxOptions.success(dataReturnedFromServerWhenSuccess);
    equals(ajaxOptions.data, 'id=1', 'query string ok');
    ok(true, 'Some other tests for results of myAjaxFunction()');
    });

    Best regards,
    ChrisRaven

  • Pingback: blog.tomaszozga.com » Blog Archive » Naśladowanie odpowiedz AJAX – mock ajax

  • http://bassistance.de/ Jörn Zaefferer

    That would've been very helpful to have in the documentation above – saw this comment only after finding the data-parsing in the source code. Anyway, works great.

  • Pingback: Building Large-Scale jQuery Applications

  • http://www.jebaird.com/ jebaird

    Thanks for the great plugin! I was wondering if there were any plans to add the ability to mock ajax calls in web workers.

  • http://wojciech.oxos.pl Wojciech Kruszewski

    Can I make sure the mock request is actually called? Otherwise it'd be more like a stub (as far as I understand the terminology).

    I'm thinking of sth like {assert_called: 2} param. It'd raise an exception if conditions aren't met in several seconds.

  • jdsharp

    Hi Wojciech,

    What you're thinking about is unit testing and assertions. Mockjax just mocks or imitates a real ajax request.

    Cheers,
    - Jonathan

  • http://twitter.com/SimonDittlmann Simon Dittlmann

    Is it possible to simulate status 303 see other? I tried it like following, but it doesn't work… Any ideas?

    $.mockjax({
    url: test.fcgi,
    status: 303,
    contentType: 'text/plain',
    headers: {
    location: 'http://localhost/jsonTestFiles/testInput.json&#39;
    }
    });

  • jdsharp

    Hi Simon,

    This won't currently work, but I can make the changes to fix it.

    Can you open a ticket at:
    http://github.com/appendto/jqu

    Cheers,
    - Jonathan

  • Pingback: appendTo Attends jQuery Conference 2011: San Francisco Bay Area | appendTo - The Company Dedicated to jQuery

  • Pingback: Mocking AJAX in jQuery « Dark Views

  • Pingback: Создание большого приложения на Javascript | Javascript и все остальное

  • Pingback: Design Magazine » Extending Your jQuery Application with Amplify.js

  • Pingback: jQuery Roundup: Mockjax, ImageMapster, Face Detection

  • Pingback: Tests unitaires en JavaScript | MathieuRobin.com

  • Drew Scheit

    Great post! I know its possible to have MockJax intercept calls via $.ajax posts in ones test environment when the service isnt ready. How would you “turn off” that interception while still in test to validate a now implemented service is working as your would expect?