I’m currently in the midst of creating an application that utilizes Socket.IO for real-time communication between users. Using mocha and should.js I was able to test objects within my node app. However, I quickly found that there were some odd synchronization issues between clients that the test cases couldn’t cover. To test the interaction between clients I needed a way to programatically communicate to my node server: Enter socket.io-client.
Writing Tests For your Socket.io Application
As an example of how to test your socket.io application we’ll create a small chat application and test it using: socket.io-client, mocha and should.js.
Our chat server should be able to:
- broadcast that a new user has joined
- broadcast messages to the whole group
- handle private messages between clients
If you hit any roadblocks see Trouble shooting at the bottom of this post.
Without further ado, below is the bare essentials for our socket.IO chat server (chat-server.js) and our tests (tests/test-chat-server.js).
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
First Test
Within the describe function (line 16 in tests) we will add our first test that determines if our chat server notifies all users that a new user has joined. It’s important to disconnect both clients once this test is over, otherwise the second test will trigger this test’s ‘new user’ event.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Now that our first test is complete, let’s run the server.
1
|
|
In another terminal window we can run the tests.
1
|
|
And both tests will fail (times out to be specific)! To pass the tests we simply update the chat-server.js to the following:
1 2 3 4 5 6 7 8 |
|
When you run the tests again they should both pass.
Second Test
Now, we’ll add the second test that determines if a message sent from one client is sent to all the clients connected to the chat server. It may not initially be obvious why I’m using 3 clients, but it should be in the 3rd test. To determine if all 3 clients have received a message we keep a counter (messges) and check that each received message is the correct message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
If you run the tests again it should fail! We can fix this by updating the server code to look like:
1 2 3 4 5 6 7 8 9 10 11 |
|
Third Test
With the first two bits of functionality complete, and tested, we now need to test that 1) a client can send a private message to another client and 2) no other clients receive that message. At minimum we need 3 clients to test this condition. Once all 3 clients have connected, the 3rd client will send a private message to the first client. It’s easy to test that the first client has received the message, but how do we test that the 2nd client has not? The solution I’m using below is that the test simply waits 40 milliseconds and if only 1 message has been received, there’s a strong chance that client 2 has not received a message. I’m not sure how to write the test to be 100% sure that the client has not received the message - any thoughts?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
Once again, running the tests should fail. Lets add code to enable private messages. Ideally we’d use Redis Pub/Sub to simplify message passing, but for the sake of brevity we’ll omit it here. We’ll keep track of clients and their sockets using the clients hash. The hashe’s key will be the client’s name, and the value will be the client’s socket. When the client disconnects we delete that entry from the hash.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Congratulations, you have a node.js chat server and you’ve tested it!
Trouble Shooting
- Have you installed node.io-client, mocha and should?
- Did you install any of the modules locally, but in another folder? If so try doing a global install.
- Make sure you restart the server before each test run.
- Running
mocha -R spec
will not work within the test folder, this command looks for the test folder, socd ..
if you’re in the test folder. - The version of socket.io-client that was in the npm repositories at the time of writing this would not connect to the node server. To get the latest version I ran:
npm install https://github.com/LearnBoost/socket.io-client/zipball/master
Updates
Using coffeescript @jamescarr refactored the above code so the server starts automatically during testing: socket.io-test