Functional tests assure us that our code does what we expect it to do. In this section, we’ll develop a test for our networked file-watching server and client programs. We’ll create a mock server that conforms to our LDJ protocol while exposing flaws in the client.
After we write the test, we’ll fix the client code so that it passes. This will bring up many Node.js concepts, including extending core classes, creating and using custom modules, and developing on top of EventEmitters. But first we need to understand a problem lurking in our client/server programs as currently written.
When you develop networked programs in Node.js, they’ll often communicate by passing messages. In the best case, a message will arrive all at once. But sometimes messages will arrive in pieces, split into distinct data events. To develop networked applications, you’ll need to deal with these splits when they happen.
The LDJ protocol we developed earlier separates messages with newline characters. Each newline character is the boundary between two messages. Here’s an example of a series of messages, with newline characters specifically called out:
| | {"type":"watching","file":"target.txt"}\n |
| | {"type":"changed","timestamp":1450694370094}\n |
| | {"type":"changed","timestamp":1450694375099}\n |
Recall the service we’ve been developing so far in this chapter. Whenever a change happens, it encodes and sends a message to the connection, including the trailing newline. Each line of output corresponds to a single data event in the connected client. Or, to put it another way, the data event boundaries exactly match up with the message boundaries.
Our client program currently relies on this behavior. It parses each message by sending the contents of the data buffer directly into JSON.parse:
| | client.on('data', data => { |
| | const message = JSON.parse(data); |
But consider what would happen if a message were split down the middle, and arrived as two separate data events. Such a split could happen in the wild, especially for large messages. The following figure shows an example of a split message.

Let’s create a test service that sends a split message like this one and find out how the client responds.
Writing robust Node.js applications means gracefully handling network problems like split inputs, broken connections, and bad data. Here we’ll implement a test service that purposefully splits a message into multiple chunks.
Open your editor and enter this:
| | 'use strict'; |
| | const server = require('net').createServer(connection => { |
| | console.log('Subscriber connected.'); |
| | |
| | // Two message chunks that together make a whole message. |
| | const firstChunk = '{"type":"changed","timesta'; |
| | const secondChunk = 'mp":1450694370094}\n'; |
| | |
| | // Send the first chunk immediately. |
| | connection.write(firstChunk); |
| | |
| | // After a short delay, send the other chunk. |
| | const timer = setTimeout(() => { |
| | connection.write(secondChunk); |
| | connection.end(); |
| | }, 100); |
| | |
| | // Clear timer when the connection ends. |
| | connection.on('end', () => { |
| | clearTimeout(timer); |
| | console.log('Subscriber disconnected.'); |
| | }); |
| | }); |
| | |
| | server.listen(60300, function() { |
| | console.log('Test server listening for subscribers...'); |
| | }); |
Save this file as test-json-service.js and run it:
| | $ node test-json-service.js |
| | Test server listening for subscribers... |
This test service differs from our previous net-watcher-json-service.js in a few ways. Rather than setting up a filesystem watcher, as we did for the real service, here we just send the first predetermined chunk immediately.
Then we set up a timer to send the second chunk after a short delay. The JavaScript function setTimeout takes two parameters: a function to invoke and an amount of time in milliseconds. After the specified amount of time, the function will be called.
Finally, whenever the connection ends, we use clearTimeout to unschedule the callback. Unscheduling the callback is necessary because once a connection is closed, any calls to connection.write will trigger error events.
At last, let’s find out what happens when we connect with the client program:
| | $ node net-watcher-json-client.js |
| | undefined:1 |
| | {"type":"changed","timesta |
| | ^ |
| | |
| | SyntaxError: Unexpected token t |
| | at Object.parse (native) |
| | at Socket.<anonymous> (./net-watcher-json-client.js:6:22) |
| | at emitOne (events.js:77:13) |
| | at Socket.emit (events.js:169:7) |
| | at readableAddChunk (_stream_readable.js:146:16) |
| | at Socket.Readable.push (_stream_readable.js:110:10) |
| | at TCP.onread (net.js:523:20) |
The error Unexpected token t tells us that the message was not complete and valid JSON. Our client attempted to send half a message to JSON.parse, which expects only whole, properly formatted JSON strings as input.
At this point, we’ve successfully simulated the case of a split message coming from the server. Now let’s fix the client to work with it.