2013-04-03 16 views
15

Ich möchte einige Funktionen in einem node.js-Modul testen. Ich denke, es wäre hilfreich, sich über ein drittes Modul lustig zu machen. zu vermeiden, insbesondereVerspottende Module in Node.js für den Komponententest

die Datenbank schlägt
# models/account.coffee 
register = (email, password)-> 
    sha_sum.update(password) 
    pw = sha_sum.digest('hex') 
    user = 
     email: email 
     password: sha_sum.digest('hex') 

    users_db.save user, (err, doc)-> 
     register_callback(err) 

account_module = 
    register: register 

module.exports = account_module 

Dies ist das Modul, das ich testen will

# routes/auth.coffee 
account = require '../models/account' 

exports.auth = 
    post_signup: (req, res)-> 
     email = req.body.email 
     password = req.body.password 
     if email and password 
      account.register(email, password) 
      res.send 200 
     else 
      res.send 400 

ich, dass Schlagen diese URL mit dem richtigen Körper in der Post testen können, wollen ruft die account.register Funktion, aber ich möchte nicht, dass der Test die Datenbank trifft. Ich habe das Account-Modul noch nicht implementiert.

Die Jasmin spec # specs/auth.test.coffee beschreiben 'Registrierung', ->

request = require 'request' 
    it 'should signup a user with username and password', (done)-> 

     spyOn(account, 'register') # this does not work, account.register still called 
     url = root + '/signup' 
     headers = 
      "Content-Type": "application/json" 
     data = 
      email: '[email protected]' 
      password: 'pw' 
     body = JSON.stringify(data) 
     request {url: url, method: 'POST',json: data, headers: headers }, (err, response, body)-> 

      expect(response.statusCode).toEqual(200) 
      done() 

ich für node.js in mehrere spöttische Bibliotheken ausgesehen haben (https://github.com/easternbloc/Syringe, https://github.com/felixge/node-sandboxed-module) aber bisher Kein Erfolg. Was auch immer ich in der Spezifikation versuche, die account.register immer ausgeführt werden. Ist dieser ganze Ansatz fehlerhaft?

+0

Es ist wie horaa sieht (https://github.com/arunoda/horaa) funktionieren könnte –

+0

sinon.js Versuchen Sie, eine ausgezeichnete Stub/spy/Mock/mockServer-Bibliothek. – nottinhill

Antwort

15

Ich verwende mocha als Test-Framework und sinon für Spott, Stubing und Spionage. Ich würde vorschlagen, Sie delegieren Ihr Konto Modul an das auth.coffee Modul und verspotten es etwa so:

exports.init = function (account) { 
    // set account object 
} 

so aus dem Mokka-Test Sie können dann ein Dummy-Konto-Objekt erstellen und es mit sinon in dem eigentlichen Test verspotten.

Entschuldigung, dass ich es nicht in Coffescript geschrieben habe, aber ich bin nicht daran gewöhnt.

+0

Danke. Das funktioniert. Anstatt ein Modul zu entführen, macht dieser Ansatz Dependency-Injection und Mocking. –

+1

Sie müssen "account.register" in der Methode "beforeEach" nicht implementieren. Benutze einfach den Stub, als hätte ich einen Call 'Yield' gemacht, um einen asynchronen Callback zu machen. Sehen Sie sich das Sinon Doc für Stubs und Erträge an. – Stefan

0

Stefans Lösung funktioniert. Ich füge nur einige Details hinzu.

describe 'register', -> 
    account = response = routes_auth = null 

    beforeEach -> 
     account = 
      register: (email, pw, callback)-> 
       if email is '[email protected]' 
        callback(null, 1) 
       else 
        err = 'error' 
        callback(err, 0) 

     response = 
      send: -> {} 

     routes_auth = require('../routes/auth').init(account) 


    it 'should register a user with email and pw', (done)-> 
     req = 
      body: 
       email: '[email protected]' 
       password: 'pw' 

     resMock = sinon.mock(response) 
     resMock.expects('send').once().withArgs(200) 
     routes_auth.post_register(req, response) 
     resMock.verify() 
     done() 



    it 'should not register a user without email',()-> 
     req = 
      body:    
       password: 'pw' 

     resMock = sinon.mock(response) 
     resMock.expects('send').once().withArgs(400) 
     routes_auth.post_register(req, response) 
     resMock.verify() 

und das routes/auth.coffee Modul ...

exports.init = (account)-> 
    get_available: (req, res)-> 
     email = req.param.email 
     if not email? or email.length < 1 
      res.send 400 
      return 
     account.available email, (err, doc)-> 
      console.log 'get_available', err, doc 
      if err then res.send 401 
      else res.send 200 


    post_register: (req, res)-> 
     email = req.body.email 
     password = req.body.password 
     if email and password 
      account.register email, password, (err, doc)-> 
       if err then res.send 401 
       else res.send 200 
     else 
      res.send 400 
0

Ich habe mit gently für spöttisch und Anstoßen und mocha für Test-Framework und should.js für BDD Stil von Tests. Hier ist, wie eine Probe Unit-Test für mich wie folgt aussehen:

describe('#Store() ', function() { 
    it('will delegate the store to the CacheItem and CacheKey', function() { 
     var actualCacheKey, actualConnMgr, actualConfig, actualLogger, actualRequest; 
     var actualKeyRequest, actualKeyConfig; 

     gently.expect(
      CacheKey, 'CreateInstance', function (apiRequest, config) { 
       actualKeyRequest = apiRequest; 
       actualKeyConfig = config; 

       return mockCacheKey; 
      }); 

     gently.expect(
      CacheItem, 'CreateInstance', function (cacheKey, connectionManager, config, logger, apiRequest) { 
       actualCacheKey = cacheKey; 
       actualConnMgr = connectionManager; 
       actualConfig = config; 
       actualLogger = logger; 
       actualRequest = apiRequest; 

       return mockCacheItem; 
      }); 

     var actualApiRequest, actualCallback; 
     gently.expect(mockCacheItem, 'Store', function (request, callback) { 
      actualApiRequest = request; 
      actualCallback = callback; 
     }); 

     var callback = function() {}; 
     var apiResponse = {'item': 'this is a sample response from SAS'}; 
     Cache.GetInstance(connMgr, config, logger).Store(apiRequest, apiResponse, callback); 

     mockCacheKey.should.be.equal(actualCacheKey, 'The cachkeKey to CacheItem.CreateIntsance() did not match'); 
     connMgr.should.be.equal(
      actualConnMgr, 'The connection manager to CacheItem.CreateInstance() did not match'); 
     config.should.be.equal(actualConfig, 'The config to CacheItem.CreateInstance() did not match'); 
     logger.should.be.equal(actualLogger, 'The logger to CacheItem.Createinstance did not match'); 
     apiRequest.should.be.equal(actualRequest, 'The request to CacheItem.Createinstance() did not match'); 

     apiRequest.should.be.equal(actualKeyRequest, 'The request to CacheKey.CreateInstance() did not match'); 
     config.should.be.equal(actualKeyConfig, 'The config to CacheKey.CreateInstance() did not match'); 

     callback.should.be.equal(actualCallback, 'The callback passed to CacheItem.Store() did not match'); 
     apiResponse.should.be.equal(actualApiRequest, 'The apiRequest passed to CacheItem.Store() did not match'); 
    }); 
}); 
Verwandte Themen