2016-02-22 94 views
0

我試圖測試Hapi.js插件與註冊功能:不一致Hapi.js實驗室測試結果

exports.register = function(server, options, next) { 

    server.route({ 
     method: 'POST', 
     path: '/register', 
     config: { 
      payload: { 
       allow: 'application/json' 
      }, 
      validate: { 
       /* deleted for brevity */ 
      } 
     }, 

     handler: function(request, reply) { 

      if (!server.app.mongoose) { 

       server.log('error', 'Failed to find an active MongoDB connection.'); 

       return reply(Boom.badImplementation()); 
      } 

      var response = reply().hold(); 

      var mongoose = server.app.mongoose; 

      var User = mongoose.model('User'); 

      var password = request.payload.password; 

      return new Promise(function(resolve, reject) { 

       bcrypt.genSalt(10, function(err, salt) { 

        if (err) { 

         server.log('error', 'Failed to generate bcrypt salt: ' + err); 

         return reject(); 
        } 

        bcrypt.hash(password, salt, function(err, hash) { 

         /* deleted for brevity */ 

         user.save(function(err, savedUser) { 

          if (err) { 

           server.log('error', 'Failed to save user to the database: ' + err); 

           return reject(Boom.conflict()); 
          } 

          server.log('debug', 'Registered new user with e-mail validation code: ' + validationCode); 

          resolve({}); 
         }); 
        }); 
       }); 

      }).then(function(data) { 

       response.statusCode = 201; 
       response.source = data; 
       response.send(); 

       return response; 

      }, function(err) { 

       if (!err) 
        err = Boom.badImplementation(); 

       response.statusCode = err.output.statusCode; 
       response.source = err.output.payload; 
       response.send(); 

       return response; 
      }); 
     } 
    }); 

    next(); 
}; 

我的測試文件是在這裏:

const Lab = require('lab'); 
const expect = require('code').expect; 

const server = require('../'); 
const lab = exports.lab = Lab.script(); 

const mongoose = require('../plugins/mongo.js').mongoose; 

lab.experiment('Registration', function() { 

    lab.before(function(done) { 

     mongoose.connection.collections['users'].drop(function(err, resp) { 

      if (err) { 

       console.error(err); 

      } else { 

       console.log(resp); 
      } 
     }); 

     var User = mongoose.model('User'); 

     /* deleted for brevity */ 

     user.save(function(err, savedUser) { 

      if (err) { 

       server.log('error', 'Failed to save user to the database: ' + err); 

       done(err); 
      } 

      done(); 
     }); 
    }); 

    lab.test('/register endpoint with empty payload', function(done) { 

     server.inject({ 
      method: 'POST', 
      url: '/register', 
      payload: {} 
     }, function(response) { 

      expect(response.statusCode).to.be.equal(400); 
      expect(response.result.message).to.match(/^child "\w+" fails because \["\w+" is required\]$/); 

      done(); 
     }); 
    }); 

    lab.test('/register endpoint with invalid email', function(done) { 

     server.inject({ 
      method: 'POST', 
      url: '/register', 
      payload: { 
       ... 
      } 
     }, function(response) { 

      expect(response.statusCode).to.be.equal(400); 
      expect(response.result.message).to.be.equal('child "email" fails because ["email" must be a valid email]'); 

      done(); 
     }); 
    }); 

    lab.test('/register endpoint with short password', function(done) { 

     server.inject({ 
      method: 'POST', 
      url: '/register', 
      payload: { 
       ... 
      } 
     }, function(response) { 

      expect(response.statusCode).to.equal(400); 
      expect(response.result.message).to.startWith('child "password" fails because ["password" length must be at least'); 

      done(); 
     }); 
    }); 

    lab.test('/register endpoint with invalid password', function(done) { 

     server.inject({ 
      method: 'POST', 
      url: '/register', 
      payload: { 
       ... 
      } 
     }, function(response) { 

      expect(response.statusCode).to.equal(400); 
      expect(response.result.message).to.startWith('child "password" fails because'); 

      done(); 
     }); 
    }); 

    lab.test('/register endpoint with existing username', function(done) { 

     server.inject({ 
      method: 'POST', 
      url: '/register', 
      payload: { 
       ... 
      } 
     }, function(response) { 

      expect(response.statusCode).to.equal(409); 
      done(); 
     }); 
    }); 

    lab.test('/register endpoint with valid payload', function(done) { 

     server.inject({ 
      method: 'POST', 
      url: '/register', 
      payload: { 
       ... 
      } 
     }, function(response) { 

      expect(response.statusCode).to.equal(201); 

      done(); 
     }); 
    }); 
}); 

一切都很好,直到我說'具有現有用戶名的/註冊端點'。

現在隨後的lab命令調用會成功退出,然後失敗測試5和6(它會繼續這樣,一次成功,一次失敗)。基本上,它看起來像結果狀態代碼是在成功的測試啓動後交換的。

看起來像一個同步問題,但我找不到原因在哪裏。有任何想法嗎?

+0

以前沒見過reply()。hold()語法,但爲什麼你仍然堅持響應呢? api文檔表示將承諾包裝到可以在回覆回調中使用的對象中。 –

+0

@ simon-p-r由於API文檔中包含「處理程序方法退出後框架將立即恢復」的聲明:http://hapijs.com/api#flow-control。此外這個問題提供了類似的例子:http://stackoverflow.com/questions/29402797/how-to-reply-from-outside-of-the-hapi-js-route-handler –

+0

有問題的最後一個答案顯示你如何需要爲了答覆,我承認你已經試過了嗎?我不使用貓鼬,但是用戶回調需要嵌套在連接回調中。 –

回答

0

我設法解決這個問題,通過分離每個測試的服務器實例並僅註冊要測試的插件(多個) 。

我正在回答我自己的問題,任何可能在將來遇到同樣問題的人。

1

在您的before步驟中,將save移動到drop回調中。

在您當前的代碼中,save可能會在drop之前完成。因此,用戶可能不存在,這將導致測試5和6失敗並交替成功

+0

通過分別重建每個測試的服務器對象來解決它。不管怎麼說,還是要謝謝你。 –

相關問題