Тестирование модуля node js с внедренной зависимостью

#javascript #node.js #unit-testing #mocha.js #sinon

#javascript #node.js #модульное тестирование #mocha.js #sinon

Вопрос:

Я программист на Java, c # с более чем 10-летним опытом. Теперь мне нужно написать некоторый код на js, и я действительно чувствую себя Алисой в Стране чудес….

У меня есть myModule.js :

 module.exports = function (logger) {
return {
    read: function (param) {
        ......
        logger.eror(....)
    },

    write: function (param) {
        ......
        logger.info(....)
    }
};
  

}

The logger.js (устаревший код, я не могу его изменить) выглядит аналогично:

 module.exports = function(some_settings){
 return {
    info: function () {
        ......
    },

    error: function () {
        ......
    }
};
}
  

Важная вещь: logger не включен в MyModule с помощью require («logger»), но введен в некотором «глобальном» index.js файл, который выглядит как:

 var settings = require("../someSettings.js")();
var logger = require("../logger.js")(settings);
var myModule = require("../myModule .js")(logger);
  

Теперь я хочу написать UT для MyModule на mocha. Итак, я хочу издеваться над регистратором. И я лицом к стене.
Я попробовал proxyquire, но это не очень хорошее решение, потому что logger не включен в MyModule по require.
Я попробовал заглушку sinon и макет, например:

 var logger = require("logger.js");
var loggerMock = sinon.mock(logger);
var myModule= require("myModule.js")(loggerMock);
  

Или:

 var logger = require("logger.js");
var loggerStub = sinon.stub(logger, "info", function() {return ....});
var myModule= require("myModule.js")(loggerStub);
  

Но у меня все еще есть некоторые ошибки, такие как :
«Попытка обернуть ошибку неопределенного свойства в функцию»…

Пожалуйста, будь моим белым кроликом в этом мире свободного javascript…

Ответ №1:

Когда вы тестируете свой модуль, вы можете использовать поддельный объект для вашего объекта logger, т.Е.:

 const logger = {info: noop, error: noop, debug:...};
function noop() {}
  

или мы создадим макет объекта с sinonjs помощью, если вы предпочитаете создавать его программно и использовать шпионские функции.

Затем вы можете внедрить его, обернув определение вашего модуля в замыкание (как вы опубликовали):

 # myModule.js:

module.exports = (dep1, dep2, ...) => {
  // module definition
}
  

Или используйте rewire package, чтобы «внедрить» зависимости, охватываемые модулем (это работает только для локальных переменных, и не нужно создавать замыкание в вашем модуле):

 # myModuleTest    

myModule = rewire('./myModule');
myModule.__set__('logger', { /* fake logger */ });