Testing with EventEmitter with Sinon

894 views
Skip to first unread message

Karooga

unread,
Nov 27, 2017, 4:31:10 PM11/27/17
to Sinon.JS
Hi, 

I'm trying to create a test involving EventEmitters and Sinon.  

Test1 below shows the working version with Mocha and Chai.  I'm sure there must be a way to do this more elegantly with Sinon, although my attempts (Tests 2-4) so far have proved otherwise.  

I'm lead to believe that perhaps there is something fundamentally wrong with my understanding of Sinon or it can't be done.  I'm guessing it's the former.

Anyone able to point out where I took a wrong turn?

Thanks


/* eslint-env mocha */
'use strict'

const fs = require('fs-extra')
const path = require('path')
const EventEmitter = require('events')

const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
chai.use(chaiAsPromised)
const assert = chai.assert
const expect = chai.expect
chai.should()
const Q = require('q')
const sinon = require('sinon')

describe('Tests', function () {
  describe('asyncTesting', function () {
    
    function listFiles (directory, eventNotifier) {
      // Use the fs-events interface without promises
      fs.readdir(directory, 'utf8', (error, files) => {
        if (error) {
          console.log('error occured', error)
          throw error
        }
        eventNotifier.emit('completed', files)
      })
    }

    it('Test1: correctly lists files (without promises or sinon)', function (done) {
      // The directory C:\Temp\files contains the files file1.txt, file2.txt
      // and file3.txt
      let currentDirectory = path.normalize('C:\\Temp\\files')
      let expectedFiles = ['file1.txt', 'file2.txt', 'file3.txt']

      let listEvent = new EventEmitter()
      listEvent.on('completed', function (files) {
        files.forEach((testFile) => {
          let errorMessage = testFile + ' is not expected'
          assert.isTrue(expectedFiles.includes(testFile), errorMessage)
        })
        done()
      })

      listFiles(currentDirectory, listEvent)
    })

    async function listFilesAsync (directory, eventNotifier) {
      // Use the fs-events interface without promises but
      // force waiting until we are finished
      // console.log(eventNotifier)
      fs.readdir(directory, 'utf8', (error, files) => {
        if (error) {
          console.log('error occured', error)
          throw error
        }
        eventNotifier.emit('completed', files)
        // console.log('fired completed event')
      })
    }

    it('Test2: confirm emit was called on event', async function () {
      let currentDirectory = path.normalize('C:\\Temp\\files')

      let listEvent = new EventEmitter()
      // Makes no difference if we register the 'completed'
      // event on listEvent or not
      // listEvent.on('completed', (files) => {
      //   console.log('called completed' + files)
      // })
      // Try catch the emit
      let emitEventSpy = sinon.spy(listEvent, 'emit')
      await listFilesAsync(currentDirectory, emitEventSpy)
      emitEventSpy.restore()
      // Always fails
      return expect(emitEventSpy.calledOnce).to.equal(true)
    })

    it('Test3: correctly calls emit (with sinon but without promises)', async function () {
      // The directory C:\Temp\files contains the files file1.txt, file2.txt
      // and file3.txt
      let currentDirectory = path.normalize('C:\\Temp\\files')
      // let expectedFiles = ['file1.txt', 'file2.txt', 'file3.txt']

      let listEvent = new EventEmitter()
      // Replace the original method 'emit' with magical sinon one
      let eventSpy = sinon.spy(listEvent, 'emit')
      // let eventSpy = sinon.spy(listEvent, 'on')
      await listFilesAsync(currentDirectory, eventSpy)

      eventSpy.restore()
      // eventSpy is never called with 'emit'
      sinon.assert.called(eventSpy)
      // Would like to test returned readFiles, but this never happens
      // sinon.assert.calledWith(eventSpy, 'completed', expectedFiles)
    })

    it('Test4: following mocha spies test', async function () {
      let currentDirectory = path.normalize('C:\\Temp\\files')
      // let expectedFiles = ['file1.txt', 'file2.txt', 'file3.txt']
      let listEvent = new EventEmitter()
      let emitEventSpy = sinon.spy()
      // From https://github.com/mochajs/mocha/wiki/Spies but this can't be correct
      listEvent.on('completed', emitEventSpy)
      await listFilesAsync(currentDirectory, listEvent)
      // Always fails
      sinon.assert.calledOnce(emitEventSpy)
    })
  })
})

Reply all
Reply to author
Forward
0 new messages