Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocha, should.js and asserting an exception

I have a file app.coffee:

class TaskList

class Task
    constructor: (@name) ->
        @status = 'incomplete'
    complete: ->
        if @parent? and @parent.status isnt 'completed'
          throw "Dependent task '#{@parent.name}' is not completed."
        @status = 'complete'
        true
    dependsOn: (@parent) ->
        @parent.child = @
        @status = 'dependent'

# Prepare scope stuff
root = exports ? window
root.TaskList = TaskList
root.Task = Task

and a file called test/taskTest.coffee:

{TaskList, Task} = require '../app'
should = require 'should'

describe 'Task Instance', ->
    task1 = task2 = null
    it 'should have a name', ->
        something = 'asdf'
        something.should.equal 'asdf'
        task1 = new Task 'feed the cat'
        task1.name.should.equal 'feed the cat'
    it 'should be initially incomplete', ->
        task1.status.should.equal 'incomplete'
    it 'should be able to be completed', ->
        task1.complete().should.be.true
        task1.status.should.equal 'complete'
    it 'should be able to be dependent on another task', ->
        task1 = new Task 'wash dishes'
        task2 = new Task 'dry dishes'
        task2.dependsOn task1
        task2.status.should.equal 'dependent'
        task2.parent.should.equal task1
        task1.child.should.equal task2
    it 'should refuse completion it is dependent on an uncompleted task', ->
        (-> task2.complete()).should.throw "Dependent task 'wash dishes' is not completed."

If I run this command in terminal: mocha -r should --compilers coffee:coffee-script -R spec I have a failing test (the final one) saying that it was expecting an exception "Dependent task 'wash dishes' is not completed." but got 'undefined'.

If I change (-> task2.complete()).should.throw to -> task2.complete().should.throw by removing the parenthesis, the test passes, and fails if I don't throw the exception. But if I change the exception message to something random, it still passes. Am I doing something wrong? Shouldn't the test only pass if the message is literally "Dependent task 'wash dishes' is not completed."?

like image 749
Matthew Avatar asked Sep 22 '12 05:09

Matthew


1 Answers

You are throwing an exception with a string instead of throwing an error object. throw() looks for the latter. So your original code works if you do:

throw new Error "Dependent task '#{@parent.name}' is not completed."

If something you write in CoffeeScript is producing results that make no sense, try compiling it to js (or pasting the code into try CoffeeScript. You'll see that:

-> task2.complete().should.throw "Dependent task 'wash dishes' is not completed."

compiles to:

(function() {
  return task2.complete().should["throw"]("Dependent task 'wash dishes' is not completed.");
});

which just defines a function and does not execute it. This explains why changing the string makes no difference. I hope that helps.

like image 187
David Weldon Avatar answered Oct 15 '22 03:10

David Weldon