2014-02-19 2 views
2

У меня есть простой асинхронный код, написанный в Node.JS, который добавляет строку в Redis SET. Вот код, он будет сохранен в файле под названием redis_ops.jsNode-Redis Асинхронное тестирование с использованием mocha

var redis = require('redis'); 
exports.addUser= function(){ 
    var client = redis.createClient(); 
    client.on("error",function(err){ 
     console.log('Error'+ err); 
    }); 
    client.select(1); 
    client.sadd("users","naveen",function(err,reply){ 
     if(err) 
      throw err; 
     return reply; 

    }); 
    console.log("at the end of the adduser function") 
    } 

Поскольку client.sadd является асинхронным, функция, содержащая client.sadd возвращается до client.sdd отделки. Вот тест написано с использованием Мокко

var assert = require("assert"); 
var core = require('./redis_ops.js'); 

describe('COREAPI', function(){ 
    describe('addUser', function(){ 
     it('should return 1 if the user is added successfully', function(){ 
     assert.equal(1,core.addUser()); 

    }) 
    }) 
}) 

Тест терпит неудачу, поскольку redis_ops возвращает неопределенное (не возвращаемого значения), поскольку функция, содержащую client.sadd возвращает первый и асинхронные client.sadd возвращаются позже с предполагаемым значением для утверждается в тесте. Как проверить возвращаемое значение из асинхронного client.sadd без дублирования кода или без содержания всего кода в том же файле?

ответ

3

Mocha позволяет тестировать асинхронные функции с использованием дополнительного обратного вызова.

describe('COREAPI', function() { 
    describe('addUser', function() { 
     it('should return 1 if the user is added successfully', function (done) { 
      core.addUser(function (err, result) { 
       assert.ifError(err); 
       assert.equal(result, 1); 
       done(); 
      }); 
     }); 
    }); 
}); 

У вашего файла redis_ops.js есть проблемы. Вы не должны вызывать обратный вызов асинхронной функции. По соглашению, обратный вызов может принимать только ошибку в качестве первого аргумента (или null, если не было ошибки), и другие аргументы для результатов.

Бросок в ваш код приведет к неперехваченным исключениям, даже если вы попытаетесь его поймать, поскольку try-catch работает только для синхронного кода. Вы должны переформатировать это выглядеть следующим образом:

var client = require('redis').createClient(); 

client.on('error', function (err) { 
    console.error(err); 
}); 

exports.addUser = function() { 
    client.select(1, function (err) { 
     if (err) { 
      return callback(err) 
     } 

     client.sadd('users', 'naveen', function (err, reply) { 
      if (err) { 
       return callback(err); 
      } 

      console.log('at the end of the adduser function') 

      callback(null, reply); 
     }); 
    }); 
}; 

Или с помощью client.multi пакетирования объекта модуля Redis, exports.addUser может выглядеть следующим образом:

exports.addUser = function() { 
    var multi = client.multi(); 

    multi.select(1).sadd('users', 'naveen').exec(function (err, results) { 
     if (err) { 
      return callback(err); 
     } 

     callback(null, results[1]); 
    }); 
}; 
+1

Большое спасибо за помощь мне понять тестирования асинхронного кода ..Very полезный ответ. –

+1

С одной стороны 'core.addUser (function (err, result) {...', но с другой стороны 'export.addUser = function() {...'. Отсутствует параметр 'callback', возможно? Более того, 'client.on (« error », function (err) {callback (err);});' не может работать, поскольку в области не существует 'callback'. – Louis

+1

@Louis yup, что' callback' должен был быть ' console.error'. «Ядро» правильное, хотя, поскольку предположительно «core» является именем модуля, для которого мы добавляем функции к экспорту, т. е. верхний список находится в тестовом модуле, нижние два находятся в пределах 'core'. – qubyte

Смежные вопросы