Testing socket.io using mocha and EcmaScript 2015 syntax
Wednesday 06. May 2015
Disclaimer: If all you want is to take a look at the final setup, the TLDR is here.
socket.io is really cool. It holds your hand through the setup of real-time applications (preferably using WebSockets), and falls back to older protocols should it be needed. Some people have claimed that it’s no longer relevant since WebSockets have become standard fare for most browsers, but I still think socket.io is a viable component in a real-time stack, especially considering its excellent documentation and ease of use.
One area that can seem a bit hairy though, is testing your socket.io application. Things can quickly get out of hand when you need to listen for events asynchronously and then subsequently test the replies from the server (which might not come in the order you expect). This blog post will show you how you can setup an environment for test-driving a real-time application, using the shiny new EcmaScript 2015 syntax to boot (because, hey, it’s the future).
To run the examples in this blog post you need to enable arrow functions, which
ATOW are not yet fully enabled in iojs. You can enable them by adding the
--harmony_allow_arrow_functions flag when running your tests.1
Like rspec, mocha has an API for writing your tests.
describe groups your
test cases together,
it specifies a particular test case, and
after hooks can (and will) be used to do necessary setup/teardown.2
Let’s see how they all work together with an example.
First we define a set of constants we’ll be using throughout our test suite,
then we define a simple
describe closure to include our dummy test which
simply ensures that our root route returns 200 OK.
To setup our http server we’ll use express as our application/routing layer,
and wrap the default http server exposed by iojs/node with our own custom
close methods so we can pass in a custom port (as seen in the example above). By
allowing a custom port to be passed into the listen interface we can run our actual
application and tests simultaniously, which is pretty neat.
close are called in a
before and an
after hook respectively, which will,
unsurprisingly, run before and after the test cases within the current
The first test case (denoted by the
it function call) makes a HTTP GET call to the server,
and ensures that the recieved status code is 200 OK, which of course isn’t the case yet. Let’s
As you can see the root route simply returns a static file called
Now, when we run our test suite we get the following output.
Great - everything’s working properly. Now the real fun begins: testing socket.io connections and validating the responses from the server.
In good TDD fashion (if that’s your cup of tea) we write our tests before we implement the feature.
To properly use embrace the power of mocha we nest this second
within the previously defined one, so that the
before hook of the parent closure
is run before we run the respective hooks in our nested
describe block. This way
we start our http server before we run
Now, it’s not strictly necessary to disconnect the client(s) between each test, but I highly recommend it as maintaining state between tests when they should be able to run in any given order is a bad idea.
This new test will fail if we run mocha again (or, times out to be specific), so let’s do something about that.
All the realtime server does is broadcast the name of the newly joined user to all connected sockets (within the realtime namespace3), as well as the number of connected users4. Running the tests again we see that they both pass - hurray!
These realtime tests might seem a little bit more hairy, but all we’re doing is ensuring
new-user event is emitted from the server twice, and that the payload is
as expected (the first client’s name before the second). Since things are working as expected,
let’s wrap things up by adding another test to ensure that messages from clients are
broadcast to all other clients.
Again, we write our test.
We connect several clients using the
socket.io-client package (
client is already connected in the
hook, in case you had forgotten) and once they have connected we register their name on the server.
Our initial client then listens for the last
new-user event (when the number of users equals 3 - line 29),
and emits a message to be broadcast using the
In our defined test we await the
say event from the server, and ensure that all clients
receive the event and that the payload is as expected.
Now for the actual implementation.
And we’re green again!
And the suite is even faster than before, now that’s some mad skills right there.
Would you look at that, we’ve successfully setup a dummy project using socket.io (1.3.5), iojs, and mocha! And we wrote it all using delicious EcmaScript 2015 syntax, dayyyum. To take things a step further you might want to automate the testing or maybe define some build scripts (gulp is great for that sort of thing!). To see what that might look like, you can check out this GitHub repository.
If you’re wondering what that
_is doing there, I’m using lodash to count the number of clients since they are stored in a hash, which has a faster lookup time than an array (not that it really matters for this small example). ↩