首页 文章

模拟Node.js中的模块进行单元测试

提问于
浏览
16

我想在node.js模块中对一些函数进行单元测试 . 我认为嘲笑第3个模块会有所帮助 . 特别要避免命中数据库

# 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

这是我想测试的模块

# 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

我希望能够测试在帖子中调用 account.register 函数时使用正确的正文敲击此URL但我不希望测试命中数据库 . 我可能还没有实现帐户模块 .

茉莉花规格#specs / 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: 'user@email.com'
           password: 'pw'
       body = JSON.stringify(data)
       request {url: url, method: 'POST',json: data, headers: headers }, (err, response, body)->

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

我已经查看了几个用于node.js(https://github.com/easternbloc/Syringehttps://github.com/felixge/node-sandboxed-module)的模拟库,但到目前为止还没有成功 . 无论我在规范中尝试什么, account.register 总是被执行 . 整个方法有缺陷吗?

3 回答

  • 0

    我使用mocha作为测试框架,sinon用于模拟,存根和 Spy . 我建议你将你的帐户模块委托给auth.coffee模块并像这样模拟它:

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

    因此,从mocha测试中,您可以创建一个虚拟帐户对象,并在实际测试中使用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();
    
        });
    
    });
    

    很抱歉没有把它写在coffescript中,但我不习惯 .

  • 16

    Stefan的解决方案有效 . 我只是添加一些细节 .

    describe 'register', ->
        account = response = routes_auth = null
    
        beforeEach ->
            account =
                register: (email, pw, callback)-> 
                    if email is 'valid@email.com'
                        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: 'valid@email.com'
                    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

    我一直在使用gently进行模拟和存根,使用mocha进行测试框架,并使用should.js进行BDD样式的测试 . 以下是我对样本单元测试的样子:

    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');
        });
    });
    

相关问题