Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27306

how to assert in my tests that a Chai assertion will fail (Error vs. AssertionError)

I am puzzled by the inheritance relationship of Error and AssertionError and how that works with assert.throws.

In my test code I have:

// @flow
...
import {assert} from 'chai';
import {AssertionError}  from 'assertion-error';

describe('foo', function() {
    it('boo', function() {
        assert.throws( ()=>{throw new Error()}
                       , AssertionError); //a 
        assert.throws( ()=>{throw new AssertionError()}
                       , Error);          // b
        assert.throws( ()=>{assert.isTrue(false);}
                       , Error);          // c
        assert.throws( ()=>{assert.isTrue(false);}
                       , AssertionError); // d
    });
});

all of the above assert.throws statements succeed. I was expecting some of them to succeed and some to fail. Specifically, given that AssertionError has Error as its prototype I was expecting a to fail as a stricter type is demanded (AssertionError) than that thrown (Error). Instead it succeeded along with the rest. What gives?

The packages I am using are:

chai@4.1.2
mocha@3.5.3

update

Based on this answer I confirm that if, instead of:

import {assert} from 'chai';
import {AssertionError}  from 'assertion-error';

… I do:

const assert = require('chai').assert;
const AssertionError = require('assertion-error');

… then the results are as expected.

Upvotes: 1

Views: 1492

Answers (3)

Francois
Francois

Reputation: 3090

So I'm not a Babel user, but I installed it and tried and compiling with the preset mentioned and got the same error, I logged AssertionError and it's not being imported (undefined).

I changed the import statement to :

import {assert} from 'chai';
import AssertionError  from 'assertion-error';

And it works fine.

The reason is by doing import {AssertionError} from ... it is actually looking for an exported property of the package 'assertion-error', basically like doing require('assertion-error').AssertionError, the AssertionError class is the default export of the assertion-error package.

What's sad though, is that it fails silently, but actually, it makes sense because babel transpiles it to this, so it never checks if the property is present:

var _assertionError = require('assertion-error');

_chai.assert.throws(function () {
    throw new Error();
}, _assertionError.AssertionError);

Also, this is a bug in chai as if the 2nd argument is present, chai should consider it even if it is undefined and throw an AssertionError. It should do something like if (arguments.length === 2) { // consider the second argument } else { // do not consider it }. Pull request is on the way.

Upvotes: 1

Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27306

The statement:

import {AssertionError}  from 'assertion-error';

… fails silently and AssertionError is undefined

This, coupled with the fact that the following succeeds:

    it('weird', function() {
        assert.throws(()=>{
            throw 1;
        }, undefined);
    });

… yielded the observed situation.

Once I changed the import to read:

import AssertionError  from 'assertion-error';

… the observed situation was the expected one.

Upvotes: 0

Francois
Francois

Reputation: 3090

I just tried

const assert = require('chai').assert;
const AssertionError = require('assertion-error');

assert.throws(
    () => {
      throw new Error();
    },
    AssertionError
);

And it worked as expected... wtf enter image description here

Upvotes: 1

Related Questions