2013-04-13 20 views
1

我想爲Node構建一個簡單的登錄模塊。我試圖以TDD的方式來做,但我仍然對它很陌生,所以任何能夠幫助我更好地理解它的技巧或資源都會很棒。Node.js:遇到摩卡問題,並期望to.throwError

我的問題是當我用無效數據查詢一個數據庫,並且我在等待一個錯誤。如果我手動測試應用程序,則會引發錯誤 - 這很好。但是,當我嘗試使用Mocha和Expect.js進行測試時,我得到了Error: expected fn to throw an exception。如果我將代碼從to.throwError()切換到to.not.throwError(),則錯誤會被正確引發。我認爲這個問題是在我嘗試異步測試和錯誤處理的地方。第一次測試通過很好。

感謝您的關注。

基於SebastianG的指示新代碼

login.js

var MongoClient = require('mongodb').MongoClient; 

exports.login = function(callback, email, password) { 

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) { 
     if (err) { 

      return err; 
     } 

     var collection = db.collection('users'); 
     if (email) { 
      collection.findOne({email:email}, function(err, item) { 
      try { 
       if (err) { 
        console.log('error'); 
        throw new Error('error finding email'); 

       } else { 

         if (item) { 
          if (item.password == password) { 
          console.log('logged in'); 
          //callback(null, item); 
          //return item; 
          } else { 
           console.log('here'); 
           throw new Error('Email and password not matching'); 
          } 
         } else { 
          throw new Error('Email not found'); 
         } 
        } 
      } catch (err) { 
       console.log('catch error here'); 
       callback(err, null); 
      } finally { 
       console.log('finally here'); 
       callback(null, item); 
      } 

      }); 
     } 

    }); 
} 

測試/登錄-test.js

var expect = require('expect.js'), 
    assert = require('assert'), 
    mocha = require('mocha'), 
    mongo = require('mongodb'); 


var login = require('../login'); 

describe('login', function() { 
    it('should login a real user', function(done) { 
     expect(function() { 
      login.login(function(err, item) { 
       //console.log(item); 
       if (err) throw err; 

       done(); 
      }, 'email', 'password') 
     }).to.not.throwError(); 
    }); 
    it('should error on unfound email', function(done) { 
     expect(function() { 
      login.login(function(err, item) { 
       console.log(err); 
       if (err) throw err; 
       done(); 
      }, 'ert','wqew') 
     }).to.throwError(); 

    }); 
    it('should error on incorrect match', function(done) { 
     expect(function() { 
      login.login(function(err, item) { 
       console.log(err); 
       throw err; 
       done(); 
      }, 'email','wqew') 
     }).to.throwError(); 
    }); 
}); 

舊代碼

login.js

var MongoClient = require('mongodb').MongoClient; 

exports.login = function(email, password, callback, errCallback) { 

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) { 
     if (err) { 

      return err; 
     } 

     var collection = db.collection('users'); 
     if (email) { 
      collection.findOne({email:email}, function(err, item) { 
      try { 
       if (err) { 
        console.log('error'); 
        throw new Error('error finding email'); 
        errCallback(err); 
       } else { 

         if (item) { 
          if (item.password == password) { 
          console.log('logged in'); 
          callback(item); 
          //return item; 
          } else { 
           console.log('here'); 
           throw new Error('Email and password not matching'); 
          } 
         } else { 
          throw new Error('Email not found'); 
         } 
        } 
      } catch (err) { 
       errCallback(err); 
      } 
      }); 
     } 

    }); 
} 

測試/登錄-test.js

var expect = require('expect.js'), 
    assert = require('assert'), 
    mocha = require('mocha'), 
    mongo = require('mongodb'); 


var login = require('../login'); 

describe('login', function() { 
    it('should login a real user', function(done) { 
     assert.doesNotThrow(function() { 
      login.login('email','password',function() { 
       done(); 
      }, function(err) { 
       if (err) throw err; 
       done(); 
      }); 
     }); 
    }); 
    it('should error on unfound email', function(done) { 
     expect(function() { 
      login.login('atreq','a', function() { 
       console.log('true');   
      }, function(err) { 
       console.log(err); 
       throw err; 
     })}).to.throwError(); 

    }); 
    it('should error on incorrect match', function(done) { 
     expect(function() { 
      login.login('email','apassword', function() { 
       console.log('true'); 
       done(); 
      }, function(err) { 
       console.log(err); 
       throw err; 
      }) 
     }).to.throwError(); 
    }); 
}); 

回答

4

在異步節點代碼使用產生的異常是(至少暫時)一個好主意。有一個概念叫做Domains,它可以幫助你,但是還是非常實驗性的。

我建議這樣做的節點方式:保留您的回調的第一個參數的錯誤。小例子:

function getUserData(cb) { 
    var userData = // ... 
    if (userData === null) { 
     cb(new Error('Something bad happend.')); 
    } else { 
     cb(null, userData) 
    } 
} 

如果你想使用errorCallback因爲你已經做的使用它:不過

errCallback(new Error('Email not found')); 

比你可以做這樣的事情(大多數測試框架提供了這個輔助方法,我這不是那種熟悉摩卡和它的模塊):

it('should login a real user', function(done) { 
    login.login(function(err, item) { 
     expect(err).to.be(null); 
     expect(item).not.to.be(null); 
     done(); 
    }, 'email', 'password'); 
}); 


it('should error on unfound email', function(done) { 
    login.login(function(err, item) { 
     expect(err).not.to.be(null); 
     expect(item).to.be(null); 
     done(); 
    }, 'ert','wqew'); 
}); 
+0

感謝您的答覆。我試圖重構我的代碼以瞭解您的建議,但我不太確定如何執行測試。我用回調作爲第一個參數並用'if(err)throw err'重寫了它們,但我仍然得到相同的錯誤:期望的fn拋出異常。我將以新代碼的形式更新我的原始帖子,作爲我如何解釋您的說明。非常感謝幫忙。 – matthewpalmer

+0

你還在想同步投擲方法:)你真正想測試的是回調的錯誤參數爲空或者是一個錯誤,這取決於測試。我在我的答案中添加了一份草稿。但是,我沒有與Mocha和expect.js一起工作,所以不要指望它能以這種方式工作。這只是一個想法。 –

+0

驚人的 - 它與'expect(err).to.be.a(錯誤)'一起工作,正如你所建議的那樣。非常感謝你的幫助!我確實欠你一個。 – matthewpalmer