Тестирование Node.js, макет и тестирование модуля, который был необходим? - PullRequest
6 голосов
/ 05 марта 2012

Я изо всех сил пытаюсь написать высококачественные тесты для моих узловых модулей.Проблема в том, что требуется модуль системы.Я хочу иметь возможность проверить, что определенный модуль имеет метод или его состояние изменилось.Кажется, здесь есть две относительно небольшие библиотеки, которые можно использовать: node-аккуратно и издевательства .Тем не менее, из-за их низкого «профиля», это заставляет меня думать, что либо люди не проверяют это, либо есть другой способ сделать это, о котором я не знаю.

Как лучше всего выполнить макет и протестировать модуль, который был необходим?

Ответы [ 3 ]

11 голосов
/ 03 июня 2012

----------- ОБНОВЛЕНИЕ ---------------

узел-песочница работает по тем же принципам, что указаны ниже, но обернута в хороший модуль.Мне очень приятно работать.


--------------- подробный awnser ---------------

После долгих испытаний я обнаружил, что лучший способ для проверки узловых модулей изолированно во время макетирования - использовать метод Войты Джины для запуска каждого модуля в виртуальной машине сновый контекст как объяснено здесь .

с этим модулем тестирования vm:

var vm = require('vm');
var fs = require('fs');
var path = require('path');

/**
 * Helper for unit testing:
 * - load module with mocked dependencies
 * - allow accessing private state of the module
 *
 * @param {string} filePath Absolute path to module (file to load)
 * @param {Object=} mocks Hash of mocked dependencies
 */
exports.loadModule = function(filePath, mocks) {
  mocks = mocks || {};

  // this is necessary to allow relative path modules within loaded file
  // i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some
  var resolveModule = function(module) {
    if (module.charAt(0) !== '.') return module;
    return path.resolve(path.dirname(filePath), module);
  };

  var exports = {};
  var context = {
    require: function(name) {
      return mocks[name] || require(resolveModule(name));
    },
    console: console,
    exports: exports,
    module: {
      exports: exports
    }
  };

  vm.runInNewContext(fs.readFileSync(filePath), context);
  return context;
};

можно протестировать каждый модуль с его собственным контекстом и легко заглушить все внешниеdependencys.

fsMock = mocks.createFs();
mockRequest = mocks.createRequest();
mockResponse = mocks.createResponse();

// load the module with mock fs instead of real fs
// publish all the private state as an object
module = loadModule('./web-server.js', {fs: fsMock});

Я настоятельно рекомендую этот способ для написания эффективных тестов в изоляции.Только приемочные тесты должны поражать весь стек.Модульные и интеграционные тесты должны проверять изолированные части системы.

5 голосов
/ 05 марта 2012

Я думаю, что шаблон насмешки - это хорошо. Тем не менее, я обычно выбираю отправку зависимостей в качестве параметров функции (аналогично передаче зависимостей в конструкторе).

// foo.js
module.exports = function(dep1, dep2) {
    return {
        bar: function() {
            // A function doing stuff with dep1 and dep2
        }
    }
}

При тестировании я могу отправлять макеты, пустые объекты вместо всего, что кажется подходящим. Обратите внимание, что я делаю это не для всех зависимостей, в основном только для ввода-вывода - мне не нужно проверять, чтобы мой код вызывал path.join или что-то еще.

Я думаю, что "низкий профиль", который заставляет вас нервничать, обусловлен несколькими причинами:

  • Некоторые люди структурируют свой код, похожий на мой
  • У некоторых людей есть собственный помощник, выполняющий ту же задачу, что и издевательство и др. (Это очень простой модуль)
  • Некоторые люди не проводят юнит-тестирование таких вещей, вместо этого раскручивая экземпляр своего приложения (и БД и т. Д.) И тестируя его. Более чистые тесты, и сервер настолько быстр, что не влияет на производительность теста.

Короче говоря, если вы считаете, что издевательство подходит вам, сделайте это!

1 голос
/ 23 июня 2013

Вы легко издеваетесь над требованием, используя "a": https://npmjs.org/package/a

//Example faking require('./foo') in unit test:
var fakeFoo = {};
var expectRequire = require('a').expectRequire;
expectRequire('./foo).return(fakeFoo);


//in sut:
var foo = require('./foo); //returns fakeFoo
...