Naming
First of all, I encourage you to change a few token names around in your unit test file. You have:
var TextAnalytic = require('../index.js');
var text = require('textanalytics');
var textanalytic = new text(config);
CamelCase tokens are conventionally used for classes (ie. things that require a new
). It's also conventional to use the name of the package for its required variable. (eg. var p = require('p')
) However, our package name is super long, so let's abbreviate it. We could abbreviate it 'textanalytic' (rather than 'TextAnalytic', because it's not a class), but that might be confusing against the actual textanalytics package.
The textanalytics package, on the other hand, does import a class definition, so CamelCase is good for that. However, the name is TextAnalytics, not TextAnalytic. So I might recommend something like this:
var middleware = require('../index.js');
var TextAnalytics = require('textanalytics');
var textanalytics = new TextAnalytics(config);
Importing
This is a minor thing, but there are two things to note about require('../index.js')
:
-
You don't need to include '.js' in require statements due to how Node searches for files, and
-
when a package.json file is present (ie. when you're importing a full module), you can just specify the directory to import rather than a specific file. So you might consider:
var middleware = require('..');
(Again, not a big deal. But if you change the name of index.js, you won't have to change it in your tests. )
Stubbing Classes
The broken unit test problem is related to how classes work in JS. This is a little inane, so I'll try to be clear.
When you write a class in JS (as you have in textanalytics), you're changing what is called the "prototype" for an object. This is a form of inheritance. Changing an object's prototype means that any object of that type will "inherit" changes to the prototype. Traditionally we did this like so:
TextAnalytics.prototype.analyze = function () { ... }
Then for any TextAnalytics object, there would be a "free" analyze()
function that comes with it. Today we write that same code with a more object-oriented look and feel:
class TextAnalytics {
analyze() { ... }
}
This is (roughly) the same code.
SO, what does this mean for your unit tests? Instead of stubbing out the analyze() function on a particular object, as you're doing here:
var text = require('textanalytics');
var textanalytic = new text(config);
this.analyze = sinon.stub(textanalytic, 'analyze');
You need to stub the object's prototype, like so:
var text = require('textanalytics');
this.analyze = sinon.stub(text.prototype, 'analyze');
Or, with our new naming convention:
var TextAnalytics = require('textanalytics');
this.analyze = sinon.stub(TextAnalytics.prototype, 'analyze');
Now all calls to analyze()
by any TextAnalytics object will go through your stub.
Hopefully that makes sense. Good luck!!