HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Javascript static and prototype mocking

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mockingjavascriptprototypeandstatic

Problem

I'm writing unit-tests for my Node.js/Express application with REST endpoints which retrieve stuff via Mongoose from db. Since I'm testing only route functions I want to mock Mongoose by providing custom request and response functions etc. I also had to mock my Person mongoose schema module with mockery.

Here is my api-endpoint functions:

/* GET one person */
function getPerson(req, res, next) {
    Person.findOne({_id: req.params.id}, function(err, person) {
        if (!person) {
            res.status(404);
            res.json({
                message: "ERROR: Person with id: " + req.params.id + " was not found from database."
            })
        } else {
            res.json(person)
        }
    });

}

/* POST one person */
function postPerson(req, res, next) {
    console.log(Person);
    var p = new Person(req.body);
    p.save(function(err) {
        console.log(p);
        console.log(Person);
        if (err) {
            res.status(400);
            res.json(err);
        }
        else {
            var r = {
                message: "New person created",
                person: p
            };
            res.json(r);
            res.status(201);
        }
    });
}


The important part is that the Person schema can be called in two ways:

Person.save(function(){}) //static function
var p = new Person(req.body);
    p.save(function(err){}) //instance function


Here is my mockery mock for Mongoose schema of Person:

```
function MockPerson(person) {

this.content = {};
for (var k in person) {
if (person.hasOwnProperty(k)) {
this.content[k] = person[k]; //add person's properties here to simulate Mongoose's Object
}
}

}
MockPerson.prototype.find = function(params, callback) {
console.log("mockfind");
return null
};
//Ugly. Note that in JS prototype functions are accessible only from instances and statics only from class.
//Mongoose supports both Person.findOne and var p = new Per

Solution

You have a couple HTTP return codes here in there in your code, but don't explain what each return code means.

I recommend creating an object of the error codes with descriptive names so you can use those in place of just the plain code; it'll aid your readability greatly.

Here is what I came up with:

var HTTP_CODES = {
    CLIENT = {
        NOT_FOUND: 404,
        BAD_REQUEST: 400
    },
    SUCCESS = {
        CREATE:201
    }
}


Then, you can easily access these codes like this, for example:

res.status(HTTP_CODES.CLIENT.NOT_FOUND);


Notice how I used all capitals for the naming? Generally across other languages, all capital letters is used for constant values.

From postPerson,

if (err) {
    res.status(400);
    res.json(err);
}
else { // <----------
    var r = {
        message: "New person created",
        person: p
    };
    res.json(r);
    res.status(201);
}


Typically, the else { will come on the same line as the close } of the preceding if statement.

You wrote it the correct way in getPerson so I don't know why you changed it.

function MockPerson(person) {

    this.content = {};
    for (var k in person) {


The signature of MockPerson should not be indented.




I realized that prototype functions are only accessible in instances
of Person and statics only from "class" Person

The line you entered after:

MockPerson.prototype.findOne = MockPerson.findOne = function(params, callback)


Looks perfectly fine to me. However, do you really need to have a method that can be accessed as static and from an instance?

You say in a comment:

//Mongoose supports both Person.findOne and var p = new Person(); p.findOne() so we need both prototype and static functions


"Mongoose supports...". I don't know much about Mongoose, but if it supports both, can't you choose one?

Code Snippets

var HTTP_CODES = {
    CLIENT = {
        NOT_FOUND: 404,
        BAD_REQUEST: 400
    },
    SUCCESS = {
        CREATE:201
    }
}
res.status(HTTP_CODES.CLIENT.NOT_FOUND);
if (err) {
    res.status(400);
    res.json(err);
}
else { // <----------
    var r = {
        message: "New person created",
        person: p
    };
    res.json(r);
    res.status(201);
}
function MockPerson(person) {

    this.content = {};
    for (var k in person) {
MockPerson.prototype.findOne = MockPerson.findOne = function(params, callback)

Context

StackExchange Code Review Q#93263, answer score: 4

Revisions (0)

No revisions yet.