2013-11-07 3 views
1

Попытка встать на скорость с помощью node.js и nodeunit, но я нахожу проблему с nodeunit, где он не видит вызов test.done() в одном из тестов.Nodeunit not detecting done()

Код:

// Added for clarity. 
var client = require("restify").createJsonClient({ 
    "version": "*", 
    "url": "http://localhost:" + server.Port 
}); 

exports["tests"] = { 
    "setUp": function (callback) { 
     server.StartServer(); 
     callback(); 
    }, 
    "tearDown": function (callback) { 
     callback(); 
    }, 
    "CanIHaveSomeTeaPlease?": function (test) { 
     test.expect(4); 
     client.get("/tea", function (err, req, res, data) { 
      test.equal(err.statusCode, 418, "Expected ImATeapot Error."); 
      test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit."); 
      test.equal(err.restCode, "ImATeapotError"); 
      test.equal(err.name, "ImATeapotError"); 
      test.done(); 
     }); 
    }, 

    // Note: I expect this test to fail as it is a copy of the above 
    //  test on a different url that doesn't return the ImATeapot 
    //  HTTP error. But it doesn't look like it's detecting it 
    //  properly. 

    "TakeThisInfo": function (test) { 
     test.expect(4); 
     client.put("/push", { 
      "hello": "world" 
     }, function (err, req, res, data) { 
      test.equal(err.statusCode, 418, "Expected ImATeapot Error."); 
      test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit."); 
      test.equal(err.restCode, "ImATeapotError"); 
      test.equal(err.name, "ImATeapotError"); 
      test.done(); 
     }); 
    } 
}; 

Выход:

FAILURES: Undone tests (or their setups/teardowns): 
- tests - TakeThisInfo 

To fix this, make sure all tests call test.done() 

Я надеюсь, что это что-то глупо.

Версии: -

Node: 0.10.21 
NPM: 1.3.11 
Nodeunit: 0.8.2 
Grunt-CLI: 0.1.10 
Grunt: 0.4.1 
+0

Действительно ли работает '/ push' (независимо от того, какой статус он возвращает), когда вы используете что-то вроде curl? – robertklep

+0

Yep работает нормально. – Nalum

ответ

3

Во-первых, я не знаю, что «сервер» в вашем коде, но я бы ожидать, что это будет асинхронно, так что-то больше, как это в вашей функции настройки:

function (callback) { 
    server.StartServer(function(){ 
    callback(); 
    }); 
} 

Во-вторых, держите подарок, что nodeunit executes the startUp and the tearDown functions after and before EVERY test, поэтому я подозреваю, что вы запускаете свой сервер 2 раза (как в tearDown, вы на самом деле не закрываете его).

+0

Добавление обратного вызова, как вы предложили, похоже, не работает. Я откладываю это на то, что я не убивал сервер в функции разрыва. См. Мой ответ за то, что я сделал. – Nalum

1

Я подозреваю, что вы на самом деле не вызывая в этом втором тесте test.done(). Положите вызов console.log(), чтобы убедиться, что вы действительно звоните.

FWIW, я воспроизвел описанную проблему, используя упрощенную версию вашего теста, ниже. Если вы опустите обработчик on('error', function() {...}), то 2-й тест не завершится. Таким образом, моя теория заключается в том, что ваша конечная точка /push вызывает другое поведение в модуле восстановления. То есть вы уверены, что restify ссылается на ваш обратный вызов с собственностью err или делает что-то другое? ... например, например, испускание события, такого как http.get, происходит ниже.

var http = require('http'); 

exports.test1 = function (test) { 
    test.expect(1); 
    http.get({hostname: "www.broofa.com", path: "/"}, function (res) { 
    test.equal(res.statusCode, 200, 'got 200'); 
    test.done(); 
    }); 
}; 

exports.test2 = function (test) { 
    test.expect(1); 
    http.get({hostname: "www.no-such-domain.com", path: "/"}, function (res) { 
    test.equal(res.statusCode, 200, 'got 200'); 
    test.done(); 
    }).on('error', function() { 
    // Comment line below out to repro the "Undone tests" error 
    test.done(); 
    }); 
}; 
+0

Мое понимание восстановления клиента JSON заключается в том, что требуется один обратный вызов для put/get/post/etc. запрос, который получает ошибки и ответы об успешности. Поэтому 'test.done()' нужно вызывать независимо. Я поместил 'console.log' в 3-х местах, и похоже, что функция обратного вызова не запускается. – Nalum

+0

, поэтому, если обратный вызов не запущен, проблема не связана с nodeunit. это либо с вашим кодом, либо с восстановлением.Попробуйте воспроизвести проблему, используя собственный API-интерфейс 'http.get()' узла. Вы можете обнаружить какое-то неожиданное поведение в коде сервера. (например, не отправлять назад заголовки или неожиданный код состояния http ... или что-то подобное.) – broofa

1

Я работаю над этим, разворачивая сервер в свой собственный процесс в настройке, а затем убивая его при разрыве. Подумайте, что проблема связана с создаваемым сервером и не выключением. Спасибо @matteofigus за это.

var cp = null; // child process 
exports["tests"] = { 
    "setUp": function (callback) { 
     cp = fork("./lib/server.js", {"silent": true}); 
     callback(); 
    }, 
    "tearDown": function (callback) { 
     cp.kill("SIGHUP"); 
     callback(); 
    }, 
    "CanIHaveSomeTeaPlease?": function (test) { 
     test.expect(4); 
     client.get("/tea", function (err, req, res, data) { 
      test.equal(err.statusCode, 418, "Expected ImATeapot Error."); 
      test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit."); 
      test.equal(err.restCode, "ImATeapotError"); 
      test.equal(err.name, "ImATeapotError"); 
      test.done(); 
     }); 
    }, 
    "TakeThisInfo": function (test) { 
     test.expect(1); 
     client.put("/push", { 
      "hello": "world" 
     }, function (err, req, res, data) { 
      test.ok(false); 
      test.done(); 
     }); 
    } 
}; 
2

Я провел последние пару часов баловаться с этим вопросом, и что стало ясно, что nodeunit не имеет возможностей поймать и исключение отображения брошенных в функциях, которые запускаются позже с помощью IO или типа SetTimeout обработать. Учитывая, как работает JavaScript, это не удивительно. Все работает, как только вы уверены, что нет исключений, но если у вас есть ошибка в вашем коде, вы получите сообщение «отменить тесты» и ничего больше. Вот что я сделал, чтобы решить свои проблемы (с использованием restify маршрута в качестве примера):

function myRoute(req, res, next) { 
    try { 
     // your code goes here... 
    } 
    catch (err) { 
     // write it to the console (for unit testing) 
     console.log(err); 
     // pass the error to the next function. 
     next(err); 
    } 
} 

После того, как я понял проблему таким образом, фиксируя его, потому что намного более ясно, и я был в состоянии получить все мои тесты пройдут!

+0

Хорошая добыча! Они должны поместить это в тест справки для Nodeunit, поскольку это почти всегда было моей проблемой при работе над тестами. – Brad

+0

Также проверьте это для твердого решения: http://stackoverflow.com/a/20038890/362536 – Brad