title: In NodeJS, how do I test for an event emitted by a class method that parses a POST API request?
body: <p>Basically, I'm testing a StreamReader that emits events when a POST request executes causing the stream reader to parse and emit a <code>data</code> event.</p>
  
  <p>I'm using <code>mocha</code>, <code>chai</code> (with <code>chai-http</code>), and <code>sinon.spy</code> to test a specific scenario in which a class that calls a REST API receives a response and then emits a "data" event in the response handler to other event listeners.</p>
  
  <p>I've read a lot about using <code>chai-http</code> with Promises to test the response with assert and expect. To that end, I am attempting to use the same pattern to test for a data event, but even with Promises, the <code>sinon.spy</code> listener is not triggered until after the Promise is fulfilled and test case is complete.</p>
  
  <p>On to the test cases...</p>
  
  <p><strong>FIRST ATTEMPT - Using <code>sinon.spy</code> as a callback</strong></p>
  
  <pre><code>it('should emit a "data" event when one record is POSTed and parsed', function() {
    let spy = sinon.spy();
    let reader = new Reader(sync_query);
    reader.on('data', spy);
    return chai.request(SYNC_URI)
      .post('/db/_bulk_docs')
      .set("Content-type", "application/json")
      .send({ "docs": [{"user": "tempura"}, {"user": "shrimp"}] })
      .then(function(response){
        expect(response.body).to.have.lengthOf(2);
        sinon.assert.calledOnce(spy);  
        // Executes too soon. I can see the event in another listener's logs. 
        // I'd like the test to run until the spy fires or a timeout occurs.
      })
      .catch(function(error) {
        throw error;
      });
      // EXITS BEFORE EVENTS are triggered?
  });
  </code></pre>
  
  <p><strong>EDIT 1 - Using a standard callback</strong></p>
  
  <pre><code>it('should emit a "data" event when one record is POSTed and parsed', function() {
    let reader = new CouchReader(sync_query);
    // This works perfectly to catch when the event is fired but...
    reader.on('data', function(evt) {
      try {
        assert.isOk(evt);
        done();
      } catch (error) {
        done(error);
      }
    });
    chai.request(SYNC_GATEWAY_URI)
      .post('/db/_bulk_docs')
      .set("Content-type", "application/json")
      .send({ "docs": [{"user": "toszter"}, {"user": "bartacus"}] })
      .then(function(response){
        // ...the next expect doesn't get caught when thrown.
        // Can't return chai.request as a promise b/c of the callback.
        expect(response.body).to.have.lengthOf(3);
      })
      .catch(function(error) {
        throw error;
      });
    this.timeout(4000);
  });
  </code></pre>
  
  <p>I wonder if... </p>
  
  <ol>
  <li>I should transform the code below into a deferred promise and return the whole block to mocha since the assertions in <code>chai.request</code> are orthogonal to the assertion in the callback, but both affect the outcome of the test, OR ...</li>
  <li>I should split this into two separate tests that test the units individually... one for the call back event emit, and the other for the response to the <code>/db/_bulk_docs</code> request?</li>
  </ol>
  
  <p>Your vote probably is with Option 2, yes?</p>
  
  <p>I've tried using a non-Promise version by passing in <code>done</code> (correctly?), then <code>setImmediate()</code> and now considering <code>process.nextTick()</code> but first, I as others with more experience using mocha (etc.) to test similar scenarios: </p>
  
  <ol>
  <li>How do we prevent the test case from finishing until an event is either caught by the listener or timeout after 30s of silence?</li>
  <li>Should I be using a vanilla NodeJS <code>request</code> module instead?</li>
  </ol>
  
  <p>Pardon me if there's a duplicate out there, but in my searches, I couldn't find one...</p>