Cómo simular dependencias para pruebas unitarias con módulos ES6
Estoy tratando de jugar con los módulos Ecmascript 6 usando webpack + traceur para transpilar a ES5 CommonJS, pero estoy teniendo problemas para probarlos con éxito.
He intentado usar el preprocesador Jest + traceur, pero el automocking y los nombres de dependencias parecen volverse locos, además parece que no puedo hacer que sourceMaps funcione con la depuración de Jest y node-inspector.
¿Hay un mejor marco para probar unitariamente los módulos ES6?
5 answers
He comenzado a emplear el estilo import * as obj
dentro de mis pruebas, que importa todas las exportaciones de un módulo como propiedades de un objeto que luego se pueden burlar. Me parece que esto es mucho más limpio que el uso de algo como rewire o proxyquire o cualquier técnica similar.
No puedo hablar por traceur, que fue el marco utilizado en la pregunta, pero he encontrado que esto funciona con mi configuración de Karma, Jasmine y Babel, y lo estoy publicando aquí, ya que parece ser la pregunta más popular de esta tipo.
He usado esta estrategia más a menudo cuando necesito burlarme de las acciones Redux. He aquí un breve ejemplo:
import * as exports from 'module-you-want-to-mock';
import SystemUnderTest from 'module-that-uses-above-module';
describe('your module', () => {
beforeEach(() => {
spyOn(exports, 'someNamedExport'); // mock a named export
spyOn(exports, 'default'); // mock the default export
});
// ... now the above functions are mocked
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-16 18:14:40
Si está utilizando Webpack otra opción que tiene un poco más de flexibilidad que rewire es inject-loader.
Por ejemplo, en una prueba que se incluye con Webpack:
describe('when an alert is dismissed', () => {
// Override Alert as we need to mock dependencies for these tests
let Alert, mockPubSub
beforeEach(() => {
mockPubSub = {}
Alert = require('inject!./alert')({
'pubsub-js': mockPubSub
}).Alert
})
it('should publish \'app.clearalerts\'', () => {
mockPubSub.publish = jasmine.createSpy()
[...]
expect(mockPubSub.publish).toHaveBeenCalled()
})
})
Inject-loader, de manera similar a proxyquire, al menos permite inyectar dependencias antes de importar, mientras que en rewire debe importar primero y luego rewire, lo que hace imposible burlarse de algunos componentes (por ejemplo, aquellos que tienen alguna inicialización).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-06 11:38:24
En realidad conseguí que esto funcionara dejando caer la broma y yendo con Karma + Jasmine + Webpack y usando https://github.com/jhnns/rewire para simular dependencias
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-30 18:09:14
Hola podría usar proxyquire:
import assert from 'assert';
import sinon from 'sinon';
import Proxyquire from 'proxyquire';
let proxyquire = Proxyquire.noCallThru(),
pathModelLoader = './model_loader';
describe('ModelLoader module.', () => {
it('Should load all models.', () => {
let fs, modelLoader, ModelLoader, spy, path;
fs = {
readdirSync(path) {
return ['user.js'];
}
};
path = {
parse(data) {
return {name: 'user'};
}
};
ModelLoader = proxyquire(pathModelLoader, {'fs': fs, 'path': path});
modelLoader = new ModelLoader.default();
spy = sinon.spy(modelLoader, 'loadModels');
modelLoader.loadModels();
assert(spy.called);
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-31 19:57:58
Proxyquire le ayudará, pero no va a funcionar con módulos webpack+ES6 modernos, es decir, "alias".
import fs from 'fs';
import reducers from 'core/reducers';
...
proxyquire('../module1', {
'fs': mockFs, // this gonna work
'core/reducers': mockReducers // what about this?
});
that
no funcionará.
Mientras puedas burlarte de fs - no puedes burlarte de reductores.
Debe especificar real
el nombre de la dependencia, después de cualquier transformación de webpack o babel. Normalmente-nombre relativo a la ubicación del modulo1. Puede ser../../../ shared / core / reducers'. Puede que no.
Hay caída en soluciones - https://github.com/theKashey/proxyquire-webpack-alias (estable, basado en fork de proxyquire) o https://github.com/theKashey/resolveQuire (menos estable, se puede ejecutar sobre proxyquire original)
Ambos funcionan también, y se burlarán de cualquier módulo ES6(son buenos) de una manera proxyquire(es una buena manera)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 22:12:29