I’m brand-spanking new to the whole stack – javascript, node.js, coffeescript, nodeunit. Think I should do it step by step? You’re probably right, but I still am not going to do it.
Here is the test file:
testCase = require('nodeunit').testCase
Server = require('./web').WebServer
Client = require('../lib/client').Client
Request = require('../lib/request').Request
OPTIONS = {host: 'localhost', port: 8080, path: '/', method: 'GET'}
SERVER = new Server OPTIONS.port
CLIENT = new Client
REQUEST = new Request OPTIONS
SERVER.start() # asynchronous!
module.exports = testCase
setUp: (callback) ->
callback()
tearDown: (callback) ->
callback()
testResponseBodyIsCorrect: (test) ->
test.expect 1
process.nextTick ->
CLIENT.transmit REQUEST #asynchronous!
process.nextTick ->
test.equal REQUEST.body, /Ooga/
test.done()
Internally, it is just a wrapper around the http library. I am using node 0.4.11.
This does not actually work. There are two asynchronous calls here. If I do this manually in the coffee REPL, it works — but nodeunit is much faster than I am, so I run into something which, to be clever, I’ll call a race condition. grin
Here is the implementation of ‘transmit’:
Http = require ‘http’
exports.Client = class Client
transmit: (request, callback = null) ->
req = Http.request request.options, (res) ->
res.setEncoding 'utf8'
res.on 'data', (chunk) ->
request.appendToResponseBody chunk
req.end()
console.log "Request sent!"
I need to make sure the server gets bound to the port before I run the test, and I need to make sure “.transmit” has finished its internal callbacks to get the response before I do the assertion.
What is the clean way (or at least the way that works) to do this?
Whenever you do something asynchronous, you should put the rest of your code in the callback from that async function. So instead of
CLIENT.transmit REQUEST
process.nextTick -> …
do
CLIENT.transmit REQUEST, (response) -> …
(I’m assuming that your
CLIENT.transmitmethod is implemented in such a way that it calls a callback with the response it gets—it should!)Now, if you’re trying to test the client and the server at the same time, then you should use an EventEmitter—I think that you’ll find that your
SERVERobject already is one, since it inherits from Node’s http.Server type. Sincehttp.Serverobjects fire arequestevent whenever they receive a request, you can do things likePretty nice, right? Node-style asynchronicity can be mind-bending, but it gives you an amazing array of options.