简体   繁体   中英

Node.js + Mocha + Should.js How to test an error being thrown by an eventemitter?

I want to test the case where an error is thrown in my search.coffee class:

Let's assume that for my test, I cn fo

search.coffee

{ EventEmitter } = require 'events'
connectors       = require './connectors'

class Search extends EventEmitter
  constructor: (@query, @credentials, dispatch = true) ->
    @connectors = @_connectors()

    if @connectors.length == 0
      # want to test this
      @emit 'error', new Error 'Search could not be dispatched to any connectors'

    @_dispatch(query, connector) for connector in @connectors if dispatch

I have tried the following, however since an event is being emitted with the error, the return of the new Search() itself does not throw an error. How can I catch this thrown error?

search_spec.coffee

Search = require '../../src/search'

describe "search.coffee", ->

  describe "constructor", ->
    it 'should return an error if no credentials match loaded connectors', ->
      new Search("foo", { }, false).should.throw()

Yeah, nothing is thrown here. The default behavior if no event listener is installed is for Node to print a stack trace and exit. It looks like a thrown exception but you can't catch it. Systems like should.throw , assert.Throw , etc. rely on being able to catch the exception. Not possible here.

Now, there's a problem. You are emitting the 'error' event in your constructor. Who has the opportunity to call the on method to install a listener so that when this emit happens, someone will receive it? The object is not constructed yet. The object could call on on itself but no one outside can.

Options:

  1. Don't emit an error, but instead throw an error. For the reason given above, this is the option I'd prefer if this were my code.

  2. Add an additional parameter to the constructor. This would be a listener that Search installs on itself right away to listen for error events. So in testing, a listener could be passed to the constructor and then you just test that it is called.

  3. If it does not make sense to allow callers to install a listener like mentioned in the 1st option, Search could install its own listener, which could record that that the object is dead (for instance, this.dead = true ). Then test for this flag.

  4. Or if the current design and behavior is the desired one (the constructor emits 'error' , which causes Node.js to exit), modify the previous option. Devise a way to indicate to Search that it is running in a test environment. When it detects that it is in testing, it adds a listener like in the previous option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM