-2

I am playing around with Mocha for the first time and I'm having difficulty to get a simple test to work. The call returns before the variable has been assigned and thus comes back as undefined.

Here is the code I would like to test:

var mongodb = require('mongodb')
var querystring = require("querystring");

var mongoURI = process.env.MONGOLAB_URI;
var dbName = process.env.dbName;

//checks for a single email address
var emailAddressExists = function () {
  var returnVal;
  mongodb.connect(mongoURI, function (err, db) {    
    if (err)
      { console.error(err); response.send("Error " + err); }

    var collection = db.collection(dbName); //, function(err, collection) {
    collection.find( { "emailAddress" : "myemail@email.com"} ).count( function (err, count)  {
      if (count == 0) {
        returnVal = false;  
        console.log("not Matched " + returnVal);           
      } else {
        returnVal = true;
        console.log("matched " + returnVal);
      }
      return returnVal;
    });
  });
)
exports.emailAddressExists = emailAddressExists;

The test I have is:

var assert = require('assert'),
    helpers = require ('../lib/helpers.js');

describe('#emailAddressExistsTest()', function() {
  var returnVal;

  it('should return 1 when the value is not present', function(done) {
    assert.equal(true, helpers.emailAddressExists(););
    done();
  });
})

When I run 'mocha' I receive the following:

#emailAddressExistsTest()
    1) should return 1 when the value is not present


  0 passing (10ms)
  1 failing

  1) #emailAddressExistsTest() should return 1 when the value is not present:
     AssertionError: true == "undefined"
      at Context.<anonymous> (test/emailAddressCheck.js:25:11)
Bob Aleena
  • 450
  • 1
  • 6
  • 16
  • `helpers.emailAddressExists(returnVal);`. It must be crashing here, because `returnVal` is not assigned any value... –  Apr 16 '15 at 16:26
  • 4
    Your function `emailAddressExists` doesn't do anything like what you probably want. You're going to want to look into callbacks. – Aaron Dufour Apr 16 '15 at 16:37
  • @MadhavanKumar - it shouldn't require returnVal to be initialized and it should be assigned a value from the emailAddressExists call right? – Bob Aleena Apr 16 '15 at 19:10
  • @AaronDufour I also tried without a parameter and instead sending 'return true' or 'return false' respectively, and calling the assertion with the call directly: e.g.: in helpers.js: 'var returnVal = function emailAddressExists() { ... //return true/false as required }' Then in the mocha test file: 'assert (true, helpers.emailAddressExists()); ' but I still get undefined. I know it has to do with callbacks, but that's what I'm trying to understand with mocha. How do I run the test so that the call doesn't return before the assignment of the value. Thanks! – Bob Aleena Apr 17 '15 at 00:23
  • @BobAleena You should focus on figuring out how callbacks work before even worrying about mocha. You might find that the answer to [this question](http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) helps. – Aaron Dufour Apr 17 '15 at 03:44
  • @AaronDufour I understand callbacks. Thank you. Perhaps my question is not clear -- What I am trying to understand is, how to test such a function with Mocha. – Bob Aleena Apr 17 '15 at 07:01
  • 1
    @BobAleena Your function doesn't do what you want it to do, to the point that nothing about it is testable. It does a database read and then throws away the result; it's a no-op. – Aaron Dufour Apr 17 '15 at 16:51
  • @AaronDufour I appreciate your feedback but you are not being helpful and if anything it feels a bit like you are making assumptions -- how exactly do you know 'what you want it to do'??. The function tests an email address and returns true/false based on the email address existing within the db. It does not throw away the result - it uses it to check the count and then returns true/false based on that. – Bob Aleena Apr 17 '15 at 16:54
  • 1
    @BobAleena It _does not_ return the result. It doesn't return anything. I am trying to be helpful, but for some reason you don't believe me. – Aaron Dufour Apr 17 '15 at 16:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/75533/discussion-between-aaron-dufour-and-bob-aleena). – Aaron Dufour Apr 17 '15 at 17:05
  • Thanks @AaronDufour - the chat has been super helpful. It seems so obvious now!! please post your solution here when you get a chance. Thanks! – Bob Aleena Apr 17 '15 at 17:18

1 Answers1

1

First, you're going to want to change emailAddressExists to take a callback - that's the only way to tell the test when you're done:

var emailAddressExists = function (next) {
  mongodb.connect(mongoURI, function (err, db) {
    if (err) {
      next(err);
    }

    var collection = db.collection(dbName);
    collection.find( { "emailAddress" : "myemail@email.com"} ).count( function (err, count) {
      if (count == 0) {
        next(null, false); 
      } else { 
        next(null, true); 
      } 
      return returnVal;
    });
  });
)

Then, you have to pass it a callback and call done in the callback:

describe('#emailAddressExistsTest()', function() {
  it('should return 1 when the value is not present', function(done) {
    helpers.emailAddressExists(function(err, returnVal) {
      // Maybe do something about `err`?
      assert.equal(true, returnVal);
      done();
    });
  });
})

You'll notice that this is a bit different from what we talked about in chat. The convention in node.js is that the first argument to a callback is an error (null if no error), and the second argument is the "return value".

Aaron Dufour
  • 17,288
  • 1
  • 47
  • 69