Conor Ginnell Conor Ginnell - 2 months ago 21
Javascript Question

TypeError: expect(...).not.toBe is not a function

Doing an exercise where I re-implement some functionality found in the Jasmine test framework. Specifically, I am running this line:

expect(false).not.toBe(true)


and I get a TypeError saying that toBe does not exist as a function. However, this line:

expect(true).toBe(true)


Passes. I suspect that it's an issue with my not() function returning this.

function ExpectedValue (val) {
this.value = val;
this.notted = false;

this.not = function() {
this.notted = !this.notted;
return this;
}

this.toBe = function(b) {
if (this.notted) {
return this.value !== b;
}
else {
return this.value === b;
}
}
}

function expect(a) {
return new ExpectedValue(a);
}

console.log(expect(false).not.toBe(true));

Answer

Jasmine's not isn't a function. Yours is. But you're using it as though it were Jasmine's (without ()):

console.log(expect(false).not.toBe(true));
// Note no () ---------------^

Your not needs to be an object with all of the methods of the object you return from expect, but with their meaning inverted, e.g.:

function ExpectedValue (val) {
    var self = this;
  
    self.value = val;

    this.not = {
        toBe: function(arg) {
            return !self.toBe(arg);
        }
    };

    this.toBe = function(b) {
        return self.value === b;
    };
}

function expect(a) {
    return new ExpectedValue(a);
}

console.log(expect(false).not.toBe(true));

There, it's manual, but that's not scaleable. Instead, you'd have an object with all of the methods on it, and create not by running through creating functions that invert the return.

arrayOfMethodNames.forEach(function(name) {
    target.not[name] = function() {
        return !target[name].apply(target, arguments);
    };
});
Comments