Как макетировать зависимости для модульных тестов с модулями ES6
Я пытаюсь возиться с модулями Ecmascript 6 с помощью webpack + traceur для транспилирования в ES5 CommonJS, но у меня возникли проблемы с их успешным модульным тестированием.
Я попытался использовать препроцессор Jest + traceur, но имена автоблокировки и зависимостей, похоже, становятся странными, плюс я не могу заставить исходные карты работать с отладкой Jest и node-inspector.
есть ли лучшая структура для модульного тестирования модулей ES6?
5 ответов:
Я начал использовать
import * as obj
стиль в моих тестах, который импортирует все экспорта из модуля как свойства объекта, который затем может быть издеваться. Я считаю, что это намного чище, чем использовать что-то вроде rewire или proxyquire или любой другой подобный метод.Я не могу говорить за traceur, который был основой, используемой в вопросе, но я обнаружил, что это работает с моей настройкой Karma, Jasmine и Babel, и я публикую его здесь, поскольку это, кажется, самый популярный вопрос этот тип.
я использовал эту стратегию чаще всего, когда нужно было издеваться над действиями Redux. Вот короткий пример:
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 });
Если вы используете Webpack другой вариант, который имеет немного больше гибкости, чем rewire inject-loader.
например, в тесте, который поставляется в комплекте с 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, аналогично proxyquire, по крайней мере, позволяет вводить зависимости перед импортом, тогда как в rewire вы должны сначала импортировать, а затем перепрограммировать, что делает невозможным издевательство над некоторыми компонентами (например, теми, которые имеют некоторую инициализацию).
Я на самом деле получил эту работу, отбросив шутку и перейдя с Karma + Jasmine + Webpack и используя https://github.com/jhnns/rewire издеваться над зависимостями
привет вы могли бы использовать 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); }); });
Proxyquire поможет вам, но он не будет работать с современными модулями webpack+ES6, т. е. "псевдонимами".
import fs from 'fs'; import reducers from 'core/reducers'; ... proxyquire('../module1', { 'fs': mockFs, // this gonna work 'core/reducers': mockReducers // what about this? });
that
не будет работать. Как долго можно издеваться над ФС - нельзя глумиться редукторы. Вы должны указатьreal
имя зависимости, после любого преобразования webpack или babel. Обычно-имя относительно местоположения module1. Могут быть.' ./../../общей/основных/редукторы'. А может и нет.есть падение в решениях - https://github.com/theKashey/proxyquire-webpack-alias (стабильный, основанный на вилке proxyquire) или https://github.com/theKashey/resolveQuire (менее стабильный, может быть запущен на оригинальном proxyquire)
оба они также работают и будут издеваться над любым модулем ES6(они хороши) в proxyquire (это хороший способ)