Skip to content

Instantly share code, notes, and snippets.

@bsatrom
Created November 8, 2011 21:56
Show Gist options
  • Save bsatrom/1349384 to your computer and use it in GitHub Desktop.
Save bsatrom/1349384 to your computer and use it in GitHub Desktop.
Samples for hooking into STDOUT for unit testing in Node.js
exports = module.exports
exports.setup = (callback) ->
write = process.stdout.write
process.stdout.write = ((stub) ->
(string, encoding, fd) ->
stub.apply process.stdout, arguments
callback string, encoding, fd)(process.stdout.write)
return -> process.stdout.write = write
var exports = module.exports;
exports.setup = function(callback) {
var write = process.stdout.write;
process.stdout.write = (function(stub) {
function(string, encoding, fd) {
stub.apply(process.stdout, arguments);
callback(string, encoding, fd);
};
})(process.stdout.write);
return function() {
process.stdout.write = write;
};
};
exports = module.exports
# server logic omitted for brevity
exports.listen = (port, host, callback) ->
try
server.listen port, host, callback
util.log "Server listening at http://#{host or "127.0.0.1"}:#{port}/"
catch err
util.log err.message
var exports;
exports = module.exports;
exports.listen = function(port, host, callback) {
try {
server.listen(port, host, callback);
return util.log("Server listening at http://" + (host || "127.0.0.1") + ":" + port + "/");
} catch (err) {
return util.log(err.message);
}
};
server = require '../js/server'
hook = require '../js/hook_stdout'
describe 'chat server', ->
it 'should listen at localhost on a port I specify', ->
unhook = hook.setup((string, encoding, fd) ->
expect(string).toContain 'Server listening at http://127.0.0.1:3001/'
)
server.listen '3001'
unhook()
@mklement0
Copy link

Great stuff, thanks for sharing; there are problems, though:

  • hook_stdout.coffee won't compile, because it contains an unexpected indent on the last line
  • hook_stdout.js won't compile, because it is missing two return statements to make it the direct translation of its .coffee source

While your technique works great for writes performed by the process itself, it doesn't for writes from child processes created with spawn and { stdio: 'inherit' }. Any idea how to fix that?

@satazor
Copy link

satazor commented Jan 14, 2016

@mklement0 I'm also looking for solutions to stdio: 'inherit'. Did you find any?

@nmccready
Copy link

@satazor and @mklement0 it is missing a return

var exports = module.exports;

exports.setup = function(callback) {
  var write = process.stdout.write;

  process.stdout.write = (function(stub) {
  //bug fix
   return  function(string, encoding, fd) {
      stub.apply(process.stdout, arguments);
      callback(string, encoding, fd);
    };
  })(process.stdout.write);

  return function() {
    process.stdout.write = write;
  };
};

@elidoran
Copy link

elidoran commented Jan 5, 2017

# this isn't necessary:
# exports = module.exports

exports.setup = (callback) ->
  write = process.stdout.write

  # use `do` to immediately call a function
  process.stdout.write = do (stub = write) ->
    (string, encoding, cb) ->
      stub.apply process.stdout, arguments
      callback string, encoding, cd
  
  # fix the indentation here, add an empty return
  return -> process.stdout.write = write ; return

Alternate version:

exports.setup = (callback) ->

  write = process.stdout.write

  # no need to do the double step above, this works:
  process.stdout.write = (string, encoding, cb) ->
    write.apply process.stdout, arguments
    callback string, encoding, cb

  -> process.stdout.write = write ; return

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment