Mocha + supertest + assert: print response body on test failure

Charles picture Charles · Aug 17, 2014 · Viewed 9.4k times · Source

I'm using mocha, supertest, and assert to test my Express app. My Express app is run in development mode so it returns useful debug info as JSON whenever a request fails. I'd like to print this data in my test suite but only when a test fails. An example of one of my tests (in CoffeeScript):

  assert  = require "assert"
  request = require "supertest"
  url     = request "http://localhost:3000"

  describe "GET /user/:id", ->
    it "should return one user", (done) ->
      url
        .get("/user" + id)
        .expect(200)
        .expect("Content-Type", /json/)
        .end (err, res) ->
          if err
            done err
          else
            # assuming the test reaches here, but fails on one of the following,
            # how do i make mocha print res.body?
            assert.equal(res.body.name, user.name)
            assert.equal(res.body.email, user.email)
            done()

How do I make mocha print res.body, but only when a test fails? I'd prefer to not have to put something like console.log(res.body) if test.failed in each describe block, if possible.

Answer

Anton Krug picture Anton Krug · Apr 26, 2016

I do it similarly:

var supertest = require("supertest");
var should    = require("should");
var util      = require('util');

describe("My test",function(){

  var response;

  it("should validate the API key",function(done){
    server
    .post("/validate")
    .set('authorization', apiKey)
    .expect("Content-type",/json/)
    .expect(200) 
    .end(function(err,res){
      response = res;
      res.status.should.equal(200);
      res.body.error.should.equal(false);
      done();
    });
  });

  afterEach(function(){
    if (this.currentTest.state == 'failed') { 
      console.log("    Response body: " + util.inspect(response.body,{depth: null, colors: true}) + "\n");
    }
  })  

});

I dedicated a response variable in my test scope, and each test sets it to the given response (response = res;). I have to do it once in each test, but then I don't have to worry when and where it fails. Before, I had to be careful, because if the test failed, some code below it wouldn't be executed, so it wouldn't even reach the print statement. This way, I save what I need, no matter what the outcome is.

Then after each test, this afterEach event will kick off and check if the test passed or failed.

  afterEach(function(){
    if (this.currentTest.state == 'failed') { 
      console.log("    Response body: " + util.inspect(response.body,{depth: null, colors: true}) + "\n");
    }
  })  

This provides a consistent way to print for each test. It's just 1 line for all the tests, so it's easy to change the format or disable, and I don't need to care where the test failed, I just care about the final result. This seems to me like the best and easiest approach, out of all the lazy approaches. Even the output JSON is nicely and colorfully displayed. There is probably a more proper way to handle it, but this is a nice, lazy approach.