1

I have some tests which call out to an HTTP API. I have mocked them out and am using a builder to create the relevant JSON so as to provide more meaning. I have used similar patterns in other languages and I am trying to get this working in javascript.

The problem I have is that even though what I create via the builder and the json object I manually construct appear (to me) equal, they are not as far as should js is concerned.

I have linked a fiddle which hopefully is clear enough to understand: https://jsfiddle.net/sp89cc95/

My builder is as follows:

var PersonBuilder = function() {
    this.name = "Bob"
  this.age = 25
  this.hobbies = ["Coding"]
}

PersonBuilder.prototype.withName = function(name) {
    this.name = name;
  return this;
}

PersonBuilder.prototype.withAge = function(age) {
    this.age = age;
  return this;
}

PersonBuilder.prototype.withHobby = function(hobby) {
    this.hobbies = [hobby]
  return this;
}

PersonBuilder.prototype.addHobby = function(hobby) {
    this.hobbies.push(hobby)
  return this;
}

Then my test setup is simply

var builder = new PersonBuilder();
var expected = {
  "name": "Bob",
  "age": 25,
  "hobbies": ["Coding"]
}

And the assertion:

builder.should.eql(expected);

This assertion fails. When I inspect the objects they both print

{"name":"Bob","age":25,"hobbies":["Coding"]}

My observations from debugging are that the array is causing the problem. When I console.log the object it shows [Object]. But if I log just the array I get ['Coding'].

I can extract the contents of the arrays manually and compare their equality, but I thought that the deep equality check of should.eql would do that for me.

Any help would be greatly appreciated. If there are better ways to write builders or test their outputs I'm all ears. This is the solution of found from a few hours of googling and some trial and error. I'm sure its something simple I'm just missing.

Thanks in advance

Shifty
  • 113
  • 2
  • 7
  • 1
    Try `JSON.stringify(builder).should.eql(JSON.stringify(expected));` – alexmac Apr 27 '16 at 19:48
  • Thanks for the answer, I feel that having a build function is the nicer way since that allows me to check the equality of the object itself and not its rendering. Though in this case it would produce the same result. – Shifty Apr 27 '16 at 20:37

1 Answers1

2

Lack of equality may be due to prototype methods, try adding build method which creates object with attributes and no prototype methods.

duncanm
  • 166
  • 1
  • 2
  • Thanks, that worked for me. I updated my fiddle with the test now passing: https://jsfiddle.net/kyvtbbes/2/ . I wonder if there is a more elegant way of cloning an object without its prototypes ? – Shifty Apr 27 '16 at 20:24
  • Use `lodash` library for that: `var builder = _.pickBy(new PersonBuilder(), function(v) { return !_.isFunction(v); })` – alexmac Apr 27 '16 at 21:42