2013-04-03 6 views
15

node.jsモジュール内でいくつかの関数をユニットテストしたい。私は第3モジュールを嘲笑することが役に立つと思います。特に、これは私がポストに正しい体と、このURLを打つことは呼び出すことをテストすることができるようにしたいユニットテストのためのNode.jsのモジュールをモックする

# 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 

をテストするモジュールであるデータベース

# 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 

を打つ避けるために、 account.register機能が、私はテストがデータベースにヒットしないようにしたい。私はまだアカウントモジュールを実装していないかもしれません。

ジャスミンスペック #仕様/ auth.test.coffee は、 'サインアップ' を記述する - >

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() 

を私はこれまでのところ(https://github.com/felixge/node-sandboxed-modulehttps://github.com/easternbloc/Syringe)Node.jsのためのいくつかのモックライブラリに見えたが、しています失敗。仕様で試してみると、いつもaccount.registerが実行されます。このアプローチ全体に欠陥がありますか?

+0

は(https://github.com/arunoda/horaa) –

+0

はsinon.jsを試してみてうまくいくかもしれない、優れたスタブ/スパイ/モック:ここでは私のためのサンプルユニットテストはどのように見えるかです/ mockServerライブラリ。 – nottinhill

答えて

15

私はmochaをテストフレームワークとして使用しています。sinonをモック、スタッフィング、スパイに使用しています。私はあなたのアカウントモジュールはauth.coffeeモジュールに委譲し、そのようにそれをあざけることをお勧め:

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

はそうモカテストからあなたは、ダミーのアカウントオブジェクトを作成することができますし、実際のテストでsinonとそれを嘲笑します。

describe('some tests', function() { 

    var account, response, testObject; 

    beforeEach(function() { 

     account = { 
      register: function() { } 
     }; 

     response = { 
      send: function() { } 
     }; 

     testObject = require('./auth'); 
     testObject.init(account); 
    }); 

    it('should test something', function() { 

     var req = { body: { email: ..., password: .... } }, // the request to test 
      resMock = sinon.mock(response), 
      registerStub = sinon.stub(account, 'register'); 

     // the request expectations 
     resMock.expect('send').once().withArgs(200); 

     // the stub for the register method to have some process 
     registerStub.once().withArgs('someargs'); 

     testObject.auth(req. response); 

     resMock.verify(); 

    }); 

}); 

申し訳ありませんが、私はそれに慣れていません。

+0

ありがとうございます。これは機能します。このアプローチは、モジュールをハイジャックするのではなく、依存性注入とモックを行います。 –

+1

'beforeEach'メソッドで' account.register'を実装する必要はありません。非同期コールバックを作るために 'yields'という呼び出しをしたように、単にスタブを使います。スタンドと収量のためのsinonの文書を見てください。 – Stefan

0

Stefanのソリューションが動作します。私はちょうど詳細を追加します。

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() 

routes/auth.coffeeモジュール...

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

私はモックとテストフレームワーク用のスタブとmochaためgentlyを使用して、テストのBDDスタイルにshould.jsてきました。それはhoraaのように見える

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'); 
    }); 
}); 
関連する問題