Question

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?

Était-ce utile?

La solution

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.transmit method 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 SERVER object already is one, since it inherits from Node's http.Server type. Since http.Server objects fire a request event whenever they receive a request, you can do things like

SERVER.on 'request', (request) ->
  test.equals REQUEST.body, request.body

Pretty nice, right? Node-style asynchronicity can be mind-bending, but it gives you an amazing array of options.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top