Kwhitejr Kwhitejr - 5 months ago 27
Javascript Question

Basic but proper use of beforeEach() or afterEach() with mocha.js and chai.js

I want to use mocha/chai to test code related to binary search trees. Here, I am testing the public

insert
method. I want to use
beforeEach()
and/or
afterEach()
hooks to reset the test environment prior to each
it()
statement so that I don't have to completely repeat the basics. However, I keep getting various errors.

Spec

describe("BinarySearchTree insert function", function() {

beforeEach(function() {
var binarySearchTree = new BinarySearchTree();
binarySearchTree.insert(5);
});

it("creates a root node with value equal to the first inserted value", function () {
expect(binarySearchTree.root.value).to.equal(5);
});

it("has a size equal to the amount of inserted values", function () {
binarySearchTree.insert(3);
expect(binarySearchTree.size).to.equal(2);
});

it("returns an error for non-unique values", function () {
binarySearchTree.insert(3);
expect(binarySearchTree.insert(3)).to.throw(String);
});

it("if inserted value is larger than current node, make or descend to rightChild", function () {
binarySearchTree.insert(3);
binarySearchTree.insert(10);
binarySearchTree.insert(7);
expect(binarySearchTree.root.rightChild.value).to.equal(10);
});

});


Error:
ReferenceError: binarySearchTree is not defined


In truth, I expected errors before there is no
afterEach()
resetting the test environment, not because
binarySearchTree
is not defined. I'd like to accomplish this, if at all possible, with only Mocha and Chai (and not other packages like Sinon, etc).

Tested Code

exports.Node = Node;

function Node(value) {
this.value = value;
this.leftChild = null;
this.rightChild = null;
}

exports.BinarySearchTree = BinarySearchTree;

function BinarySearchTree() {
this.root = null;
this.size = 0;
}

BinarySearchTree.prototype.insert = function(value) {
// 1) when root node is already instantiated
if (this.root === null) {
// tree is empty
this.root = new Node(value);
this.size++;
} else {
// 2) nodes are already inserted
var findAndInsert = function (currentNode) {
if (value === currentNode.value) {
throw new Error('must be a unique value');
}
// base case
if (value > currentNode.value) {
// belongs in rightChild
if (currentNode.rightChild === null) {
currentNode.rightChild = new Node(value);
} else {
findAndInsert(currentNode.rightChild);
}
} else if (value < currentNode.value) {
// belongs in leftChild
if (currentNode.leftChild === null) {
currentNode.leftChild = new Node(value);
} else {
findAndInsert(currentNode.leftChild);
}
}
};
findAndInsert(this.root);
this.size++;
}
};


Bonus question... I'm not sure if I am properly testing for the thrown error (when a non-unique value is inserted)?

Answer

It is undefined because it is not in test function scope. Define it one step before in describe scope. For reference, look at the Angular docs. https://docs.angularjs.org/guide/unit-testing

describe("BinarySearchTree insert function", function() {
  var binarySearchTree;
  beforeEach(function() {
    binarySearchTree = new BinarySearchTree();
    binarySearchTree.insert(5);
  });

  it("creates a root node with value equal to the first inserted value", function () {
    expect(binarySearchTree.root.value).to.equal(5);
  });

  it("has a size equal to the amount of inserted values", function () {
    binarySearchTree.insert(3);
    expect(binarySearchTree.size).to.equal(2);
  });

  it("returns an error for non-unique values", function () {
    binarySearchTree.insert(3);
    expect(binarySearchTree.insert(3)).to.throw(String);
  });

  it("if inserted value is larger than current node, make or descend to rightChild", function () {
    binarySearchTree.insert(3);
    binarySearchTree.insert(10);
    binarySearchTree.insert(7);
    expect(binarySearchTree.root.rightChild.value).to.equal(10);
  });

});
Comments