В дополнение к совету Питера Линоса позвольте мне представить вам правильную идею модульного тестирования. При выполнении модульного тестирования многие люди задают не тот вопрос. Это не «Как я проверяю это», а «Что я проверяю». В вашем случае вы хотите проверить свой код, логику и ничего больше. Это означает, что вы должны удалить все внешние факторы, включая сторонние библиотеки, модули npm и даже основные модули API node.js.
Задайте себе вопрос: можете ли вы скопировать свой набор тестов и запустить его, не тратя часы на настройку среды? Ты должен быть способен. В этом весь смысл написания модульных тестов - заставить их работать изолированно, чтобы гарантировать правильность кода. Мы называем эту «среду», в которой ваш код может работать изолированно, «контрольной средой», аналогично тому, что используется в научных кругах.
Теперь, чтобы достичь этого, вам нужно понять концепцию светильников и макетов. Светильники предназначены для создания вашей среды управления. Это достигается созданием группы фиктивных объектов, где каждый фиктивный объект принимает входные данные и создает выходные данные. Таким образом, у вас есть точный контроль над всеми аспектами вашего кода, и это упрощает тестирование всех видов вещей, от операций с БД до запросов REST.
Наконец, поняв, что:
- Лучший набор тестов - это тот, который может работать в изолированной контрольной среде
- Светильники используются для создания этой среды, предоставляя вашему коду фиктивные объекты
- Имитируемые объекты принимают входные данные и возвращают выходные данные
- Выше 3 вещи могут быть достигнуты только в том случае, если вы закодировали свой проект со 100% -ной зависимостью
Макет объектов
Предполагая, что в вашей функции foo () вы хотите прочитать содержимое файла, вот как должен выглядеть ваш макет:
var FsMock = {
readFile : function readFile(path, encoding, callback) {
if (path === 'unit-test-1')
callback(null, 'This is the file contents');
else
callback(new Error('Unexpected error');
}
}
А затем в своем тестовом коде вы пытаетесь прочитать файл «unit-test-1», и он вернет «Это содержимое файла».
Внедрение зависимостей
Все вышеперечисленное было бы чрезвычайно сложно, если бы ваш проект не был написан так, чтобы его зависимости вводились извне. В настоящее время мое соглашение состоит в том, что все модули должны иметь функцию make (), которая принимает объект, содержащий все его зависимости. Вот простой пример:
var Fs = null;
var Path = null;
var TestObj = module.exports = {
make : function make(args) {
if ('undefined' === typeof args.fs)
throw new Error('Dependency: FS module needed');
if ('undefined' === typeof args.path)
throw new Error('Dependency: Path module needed');
Fs = args.fs;
Path = args.fs;
return Object.create(this);
}
}
Тогда вам понадобится либо фабрика, либо DI-контейнер, чтобы построить этот объект для вас, автоматически создавая его зависимости.
Только тогда BDD и TDD будут интересны в вашем проекте. Надеюсь, это поможет!