Reputation: 3514
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()
Upvotes: 1
Views: 849
Reputation: 151491
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:
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.
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.
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.
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.
Upvotes: 2