Async testing with vows using the http.get library

2020-03-26 01:35发布

问题:

I'm having a doozie of a time trying to get a basic http test to work with vows.

I think I've followed the async example from vows http://vowsjs.org/#-writing-asynchronous-tests and substitued the appropriate calls, but I must be missing something.

The test code looks like this:

var http = require('http'),
    vows = require('vows'),
    assert = require('assert');

vows.describe("homepage").addBatch({
  "Get the home page": {
    topic: function() {
      http.get({'host': "127.0.0.1", 'port': 5000, 'path': '/'}, this.callback);
    },
    'should respond with 200 OK': function(res) {
      assert.equal(res.statusCode, 200);
    }
  }
}).export(module);

I get the following error when I try to run the test for this:

/Users/<home_folder>/node_modules/vows/lib/vows.js:80
rrored', { type: 'promise', error: err.stack || err.message || JSON.stringify(
                                                                    ^
TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at EventEmitter.<anonymous> (/Users/<home_folder>/node_modules/vows/lib/vows.js:80:90)
    at EventEmitter.emit (events.js:64:17)
    at /Users/<home_folder>/node_modules/vows/lib/vows/context.js:31:52
    at ClientRequest.<anonymous> (/Users/<home_folder>/node_modules/vows/lib/vows/context.js:46:29)
    at ClientRequest.g (events.js:143:14)
    at ClientRequest.emit (events.js:64:17)
    at HTTPParser.onIncoming (http.js:1349:9)
    at HTTPParser.onHeadersComplete (http.js:108:31)
    at Socket.ondata (http.js:1226:22)

I can get a simple http example to work on it's own. I can get the vows example to work on it's own but I can't combine them for whatever reason. I'd really appreciate some help here. I've been trying to get this to work for a while now (including much googling).

UPDATE:

Apparently adding an error argument to the call back solves this problem, thanks to help from Alexis Sellier (creator of vows).

But I have no idea why. When writing out the http lib example on it's own no error argument is required. I can't find any documentation in vows to indicate why it's needed so I'm at a bit of a loss.

My new question is why is the error argument required when using the http lib in vows?

回答1:

After checking vow's source code, I think I know why. Vows always ensure that when you call this.callback, the resulting receiver function's first argument is always an error object. Vows interpret the callbacks by these rules:

  1. If the first argument of your originating callback is a boolean, use that to determine whether or not to append an error object to the receiving callback (e.g. path.exists(boolean) will emit callback(error, exists) instead)

  2. If the first argument is an object, assume it's an error object and use that to determine whether to add the originating callback to the "error" or "success" list. The reason this list exists is to support promise based tests I guess?

While I can't confirm the above is correct, my experience is that vows' async style is made to support node-styled callbacks (e.g. err as the first arg), and 3rd party npm modules that don't conform to this standard will be hard to test.

Please don't take my answer as gospel, as this is my own experience. Another gotcha is when you have async operations inside the function that you want to test - unless you provide a callback, vows won't be able to handle it properly.

Personally, I think vows still make it hard to test async code. I wish it had some waitFor() or until() flow control functions though.

My suggestion? When dealing with async code, use Step. Don't let vows control your flow.



回答2:

It is actually missing in the documentations which is still a bit short. But you can get a glimpse of it here in this page :

'when peeled *asynchronously*': {
        topic: function (banana) {
            banana.peel(this.callback);
        },
        'results in a `PeeledBanana`': function (err, result) {
            assert.instanceOf (result, PeeledBanana);
        }
    }

As it was said by Morten Siebuhr and Ruben Tan, this is how vows works and that is why it works like that.