I just started nodejs development. I am testing mongodb driver but repeatedly getting assertEquals has no method.
code from sourceRepo
var client = new Db('test', new Server("127.0.0.1", 27017, {})),
test = function (err, collection) {
collection.insert({a:2}, function(err, docs) {
collection.count(function(err, count) {
test.assertEquals(1, count);
});
// Locate all the entries using find
collection.find().toArray(function(err, results) {
test.assertEquals(1, results.length);
test.assertTrue(results[0].a === 2);
// Let's close the db
client.close();
});
});
};
client.open(function(err, p_client) {
client.collection('test_insert', test);
});
Error
has no method 'assertEquals'
How to reolve it?
You can use Node's Assert for this (where it is called equal rather than equal*s*):
var assert = require('assert');
// ...
assert.equal(count, 1);
// ...
However, for Unit tests or something similar you should consider using some testing framework. eg. Jasmine for Node, which is very popular.
assert.equal is deprecated: use assert.strictEqual() instead.
assert.equal(1, '1');
// OK, 1 == '1'
assert.strictEqual(1, '1');
// FAIL, 1 === '1'
Docs: https://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message
Related
Is there a good practical example of how to use _.after method in lodash library?
Use it whenever you need to invoke a callback after it's been called n number of times.
var fn = _.after(3, function () {
console.log('done');
});
fn(); // Nothing
fn(); // Nothing
fn(); // Prints "done"
It's useful for invoking callback when all async calls are complete.
var done = _.after(3, function () {
console.log('all 3 requests done!');
});
$.get('https://example.com', done);
$.get('https://example.com', done);
$.get('https://example.com', done);
Basic game example where player dies after getting shot 3 times.
var isDead = _.after(3, function () {
console.log('Player died!');
});
player1.shoot(player2, isDead); // undefined
player1.shoot(player2, isDead); // undefined
player1.shoot(player2, isDead); // "Player died!"
Basically you use _.after in place of a manual counter.
There are not many examples out there but see the following for something that I use for my internal tooling.
Basically the following is a script to be run using Node. It removes documents from given Mongodb collections. That is it. But the idea is to close the DB connection only after all collections are cleaned up. We will use _.after method for that. You can read about after function here
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server;
_ = require('lodash');
var db = new Db('mydb', new Server('localhost', 27017));
db.open(function(err, db) {
var collectionsToClean = ['COLLECTIONA', 'COLLECTIONB', 'COLLECTIONC'];
var closeDB = _.after(collectionsToClean.length, function() {
db.close();
console.log('Connection closed');
});
_.forEach(collectionsToClean, function(collectionName) {
db.collection(collectionName, function(err, collection) {
collection.remove({}, function(err) {
if (err) {
console.log('Could not remove documents from ' + collectionName);
} else {
console.log("All documents removed from " + collectionName);
}
closeDB();
});
})
});
});
You can now use this as a template for other Mongodb shell methods.
I am using Mocha to test out some database queries I created. I need my before block to create the appropriate foreign keys so the unit tests can focus on testing out the raw create/delete functionality of my Node ORM.
My problem is that I am inserting db entries in my before block and the unit tests are running before the before block is finished executing.
I read that promises should be used to deal with this kind of thing, so I refactored my codebase to use promises but I still can't get around the fact that I need a setTimeout.
How can I perform async before block without needing to wrap my first it block in a setTimeout?
var chai = require('chai');
var expect = chai.expect;
var db = require('../server/db/config');
var models = require('../server/db/models');
describe('scoring', function() {
var testMessage = {
x: 37.783599,
y: -122.408974,
z: 69,
message: 'Brooks was here'
};
var messageId = 1;
before(function() {
var token = '' + Math.random();
models.createUser(token).then(function() {
testMessage.userToken = token;
models.insert(testMessage)
});
});
it('should have votes created in db when createVote is called', function(done) {
setTimeout(function(done) {
models.createVote(messageId, token, function(err, res) {
expect(res.insertId).to.be.a('number');
done();
});
}.bind(this, done), 1000);
});
});
You could do it like joews suggests. However, Mocha supports using promises for synchronization. You have to return your promise:
before(function() {
var token = '' + Math.random();
return models.createUser(token).then(function() {
testMessage.userToken = token;
models.insert(testMessage)
});
});
Mocha won't continue to the test until it is able to execute .then on the promise returned by your code.
The function you pass to before, like the other Mocha API methods, can accept a done callback. You should call this when your before actions have completed:
before(function(done) {
var token = '' + Math.random();
models.createUser(token).then(function() {
testMessage.userToken = token;
return models.insert(testMessage)
}).then(function() {
done();
})
});
Mocha docs - asynchronous code
I am testing my REST API with should.
At the moment i have tested my methods to work as intended via the browser, and console testing.
My test cases are turning out to work just fine when testing with should, on the GET methods from my API.
Are there any way to test the delete and post methods in should, og would i be better of to use another testing enviroment ?
Following is a snippet from my API
router.delete('/deleteProfile/:id', function (req, res) {
var toDelete = req.params.id;
dataLayer.deleteProfile(toDelete, function (err, result) {
if(err) res.status(500).send('Person + ' + toDelete+ ' not deleted')
else{
console.log(result);
res.json(result);
}
});
Following is a snippet of my test :
it("Should delete the user With the userName FrækFyr91", function (done) {
http.get("http://localhost:"+testPort+"/profileApi/deleteProfile/FrækFyr91",function(res){
res.setEncoding("utf8");//response data is now a string
res.on("data",function(chunk){
var n = JSON.parse(chunk);
n.length.should.equal(4);
done();
});
})
});
I know the http.delete wont work.
Any suggestions ?
Rather than using http, I'd recommend using one of the specialized REST client libs, like restler, which are specifically designed to communicate with RESTful routes.
You might also consider using chai for your testing assertions as it provides very comprehensive BDD-style assertions.
So instead of your:
http.get(endpointUrl,function(res){
res.on('data',...);
});
I'd use:
var mocha=require('mocha'),
should=require('chai').should(),
client=require('restler');
describe('deletions',function(){
it('should delete something',function(done){
client.del(deleteEndpointUrl).on('complete',function(result){
// if the request failed, result will be an Error
if(result instanceof Error) {
return done(result); // return error
}
// test result here
result.should.be.an.object; // chai.should extends objects with assertions
// etc.
done();
});
});
});
Is there anyway to duplicate an collection through the nodejs mongodb driver?
i.e. collection.copyTo("duplicate_collection");
You can eval copyTo() server-side though it will block the entire mongod process and won't create indexes on the new collection.
var copyTo = "function() { db['source'].copyTo('target') };"
db.eval(copyTo, [], function(err, result) {
console.log(err);
});
Also note the field type warning.
"When using db.collection.copyTo() check field types to ensure that the operation does not remove type information from documents during the translation from BSON to JSON. Consider using cloneCollection() to maintain type fidelity."
Try to avoid .eval() if this is something you want to do regularly on a production system. It's fast, but there are problems.
A better approach would be to use The "Bulk" operations API, and with a little help from the "async" library:
db.collection("target",function(err,target) {
var batch = target.initializeOrderedBulkOp();
counter = 0;
var cursor = db.collection("source").find();
var current = null;
async.whilst(
function() {
cursor.nextObject(function(err,doc) {
if (err) throw err;
// .nextObject() returns null when the cursor is depleted
if ( doc != null ) {
current = doc;
return true;
} else {
return false;
}
})
},
function(callback) {
batch.insert(current);
counter++;
if ( counter % 1000 == 0 ) {
batch.execute(function(err,result) {
if (err) throw err;
var batch = target.initializeOrderedBulkOp();
callback();
});
}
},
function(err) {
if (err) throw err;
if ( counter % 1000 != 0 )
batch.execute(function(err,result) {
if (err) throw err;
// job done
});
}
);
});
It's fast, not as fast as .eval() but does not block either the application or server.
Batch operations will generally take as many operations as you throw at them, but using a modulo as a limiter allows a little more control and essentially avoids loading an unreasonable amount of documents in memory at a time. Keep in mind that whatever the the case the batch size that is sent cannot exceed more that 16MB between executions.
Another option to duplicate a collection would be to use aggregate method on a collection and the $out parameter. Here is an example inside of an async function:
const client = await MongoClient.connect("mongodb://alt_dev:aaaaa:27018/meteor");
const db = client.db('meteor');
const planPrice = await db.collection('plan_price');
const planPriceCopy = await planPrice.aggregate([{$match: {}}, {$out: planPriceUpdateCollection}]);
await planPriceCopy.toArray();
This will create a copy of the original collection with all of its content.
I working with Soda.js, mocha and selenium RC. I'm trying to speed up my testing and one way I was thinking is since I'm starting a new session for each test (i.e. running through closing/opening an new browser and logging into a site).
I've seen numerious incomplete posts on various forums/message boards about reusing sessions for other languages but my tests are all Javascript.
Does anyone know how I can reuse the previous browser/session once I start my tests so I dont have to start a new session in each test.
My test runner for soda looks like this.
var soda = require('soda'),
util = require('util'),
//config object - values injected by TeamCity
config = {
host: process.env['SELENIUM_HOST'] || 'localhost',
port: process.env['SELENIUM_PORT'] || 4444,
url: process.env['SELENIUM_SITE'] || 'http://google.com',
browser: process.env['SELENIUM_BROWSER'] || 'firefox'
};
describe("TEST_SITE", function(){
beforeEach(
function(done){
browser = soda.createOnPointClient(config);
// Log commands as they are fired
browser.on('command', function(cmd, args){
console.log(' \x1b[33m%s\x1b[0m: %s', cmd, args.join(', '));
});
//establish the session
browser.session(function(err){
done(err);
});
}
);
afterEach(function(done){
browser.testComplete(function(err) {
console.log('done');
if(err) throw err;
done();
});
});
describe("Areas",function(){
var tests = require('./areas');
for(var test in tests){
if(tests.hasOwnProperty(test)){
test = tests[test];
if(typeof( test ) == 'function')
test();
else if (util.isArray(test)) {
for(var i=0, l=test.length;i<l;i++){
if(typeof( test[i] ) == 'function')
test[i]();
}
}
}
}
});
});
I found my answer. I really needed to be concentrating on mocha more for my answer which was along the lines of this:
//before running the suite, create a connection to the Selenium server
before(
function(done){
browser = soda.createOnPointClient(config);
// Log commands as they are fired
browser.on('command', function(cmd, args){
console.log(' \x1b[33m%s\x1b[0m: %s', cmd, args.join(', '));
});
//establish the session
browser.session(function(err){
done(err);
});
}
);
//after each test has completed, send the browser back to the main page (hopefully cleaning our environment)
afterEach(function(done){browser.open('/',function(){
done();
});
});
//after the entire suite has completed, shut down the selenium connection
after(function(done){
browser.testComplete(function(err) {
console.log('done');
if(err) throw err;
done();
});
});
The result so far was that I'm not seeing any real performance gain by reusing the session over starting a new one. My tests still take roughly the same amount of time.