JavaScript
Programming
Node.JS
Web services testing
Comments 13
0
Я подразумевал живых людей из дельта окрестности. Библиотек то – на любой вкус.
0
И jest `мокает` так же как sinon. Это не перехват внутренней зависимости модуля, а внешней.
Представим что вас есть код на реакте
 const someComponent = ()....

 const mapStateToProps = (state) => ({
   awesomeData: coolSelectorFromReduxStore
 });

 const ConnectedComponent = connect(connect(
  mapStateToProps
)(someComponent);

И вы тестируете именно ConnectedComponent. Ну бывает.
Стандартные средства заставят вас собрать правильный store, обернуть все в Provider и все будет плохо. Там нечего мокать «напрямую». Все спрятано в файле и в тесты не светит.

Rewiremock и компания же могут «по живому» перегрузить connect или coolSelectorFromReduxStore внутри файла, а не снаружи, и итоговый тест будет прост как три копейки.
0
Как будет выглядеть подобный пример, если заменить proxyquire на rewiremock?
// test.js
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const assert = require('assert');

const uptime = sinon.spy();

proxyquire('./app', { process: { uptime } });

const app = require('./app');
assert(uptime.notCalled);
app.uptime();
assert(uptime.calledOnce);

// app.js
const process = require('process');
module.exports = {
    uptime: process.uptime,
};
0
У вас не совсем корректный пример. Точнее вы не правильно используете proxyquire.
Ваш пример работает на основе паразитного сайд эффекта работы библиотеки, а точнее на основе странного поведения, когда после работы proxyquire в кеше модульной системы остается мокнутая версия process.
Буквально в следущем тесте, когда вы уже будете ожидать «нормальное» поведение — вам прилетит сюрприз.
Не делайте так. Очень много людей ночами не спали, все думали почему по одиночке их тесты работают, а все вместе — падают.
Правильный код:
const app = proxyquire.noPreserveCache().load('./app', { process: { uptime } }); // app с мокнутым process
const app = require('./app'); // "настоящий" app, как и должно быть

PS: В любом случае «нужный» app надо забирать из метода load, а не require. Даже если noPreserveCache вам не нужен.

В то же время такой код нормален для rewiremock
rewiremock('process').with({uptime});

rewiremock.enable();
const app = require('./app'); // app с мокнутым process
rewiremock.disable(); // вычистит все затронутые модули

const app = require('./app'); // "настоящий" app, как и должно быть
+1
Спасибо за доходчивое разъяснение. Насчет странного поведения, мне оно казалось вполне ожидаемым, точнее то что proxyquire заменяет кешированную версию модуля и если бы нужно было вернуть нормальное поведение я бы удалил модуль из кеша в соответствии с документацией https://nodejs.org/api/globals.html#globals_require_cache. Ваш вариант rewiremock с enable/disable действительно выглядит намного лучше и понятнее.
В readme репозитория не помешал бы список публичных методов API с их кратким описанием, а в репозитории папка examples с простыми и самодостаточными примерами без лишнего кода. В остальном rewiremock выглядит приятно, возьму на вооружение.
0

Я так понимаю вот это мораль истории:


У нормальных людей — нормальный DI.

Но когда не до этого, то rewiremock может выручить. Правильно?

0
Все верно —
От каждого по способностям, каждому по потребностям.

Если нет способностей, но есть потребности — rewiremock и аналоги помогут.
0

Отправил вам PR. А как rewiremock будет работать с паралельными тестами (как в jest/ava)? Если я правильно понимаю то так же как и другие, т.е. лучше так не делать.

0
Жил в России — все фигели от моего русского. Переехал зарубеж — теперь все фигеют от моего английского.

Насчет параллельных тестов — сразу честно — не тестировал, но должно работать. Потому что:
1. База моков — общая (надо будет сделать простой интерфейс по клонированию и ресету моков перед началом теста).
2. По enable/disable из кеша вырезаются все мокнутые файлы и все файлы что как либо от них зависят.
Итого можно быть увереным, что после enable получите ровно то, что и нужно, а после disable — все вернется на круги своя.

Единственная проблема — ресет.
Возможно вот такой код сработает:
//mocks.js
 rewireMock('file1'); // do nothing, just indicate mock, to wipe it from a cache
 rewireMock('file2');


//test.js
 rewireMock('file1').with(something); // override mock.
0
PS: Проблемы с общими моками, подключенными через третий файл — нет. У каждой инстанс сам за себя, так как rewiremock сам себя из кеша вырезает. Общий только кеш nodejs.
Only those users with full accounts are able to leave comments., please.