Catching Sinon Unmet Requests

Photo Credit: Random image from https://unsplash.it

Catching Sinon Unmet Requests

What is it?

Track AJAX requests that have not been responded to by the Sinon.JS fake XMLHttpRequest server.

Why is it important?

It can be difficult to figure out whether a request has been responded to. Figuring it out can be time consuming and troublesome. This method catches everything.

How do we do it?

I am using Mocha and Chai, but this should work as well with other frameworks’ equivalent hooks.

I use a global

1
xhr_server
variable to create the Sinon.js server like this:

  xhr_server = sinon.fakeServer.create()

Because I want to capture every AJAX request I do not put this into a

1
before
or
1
beforeEach
with matching restoration in
1
after
/
1
afterEach
. Any AJAX request made on my testing page ought to be intercepted by the fake server.

So after every test one can check the Sinon.js

1
queue
that tells us what requests were made:

  afterEach ->
    if xhr_server.queue
      # Print something that tells us what's happening.
      console.log("Unmet Requests:",
        xhr_server.queue.map((m) -> m.url).join(", ")
      )
      xhr_server.queue.length = 0
    if xhr_server.responses
      xhr_server.responses.length = 0

Note that we empty the server responses and queue for the next test.

Now whenever a request is unmet, we get:

1
>>> Unmet Requests: /test_url /test_url_2

Caveats

There are two caveats to this strategy. First, we cannot match the test that calls

1
afterEach
to the request. The queue may contain requests made by latent asynchronous calls generated in a prior test. I am not certain this is a solvable problem.

Second, and in a related vein, if any request is made after all the tests are complete those requests will not be printed to the screen.

One can solve this latter problem by changing the

1
xhr_server.xhr.onCreate
callback after the test-runner completes. For example:

mocha.run(->
   xhr_server.xhr.onCreate = (req) ->
    console.error("XHR request made to #{req.url} after tests.",
      req)
)

Summary

This is just a little trick to rein in and tame what can be a wild asynchronous world. I find it quite helpful, and hope you find it valuable.