0

I'm trying to use proxyquire to replace a method call within a module I'm testing, but it is calling the method as is despite the fact I have the stub set up. What am I doing wrong?

formsReducer.test.js:

import { expect } from 'chai';
import * as actions from '../actions/formsActions';
import * as types from '../constants/actionTypes';
import proxyquire from 'proxyquire';

describe('Forms Reducer', () => {
    describe('types.UPDATE_PRODUCT', () => {
        it('should get new form blueprints when the product changes', () => {
            //arrange
            const initialState = {
                blueprints: [
                    {
                        id: 1,
                        categoryId: 1,
                        identifier: null,
                        name: "Investment Policy Statement",
                        sortGroup: 1,
                        wetSignRequired: false
                    }
                ]
            };
            const testBlueprints = [{ id: 999, categoryId: 1, name: "Form Blueprint Loaded From Product ID 1", sortGroup: 1, wetSignRequired: false }];
            //use proxyquire to stub call to formsHelper.getFormsByProductId 
            let formsReducer = proxyquire.noCallThru().load('./formsReducer', {
              formsHelper: {
                getFormsByProductId: id => { return testBlueprints }
              }
            }).default;
            const action = {
                type: types.UPDATE_PRODUCT,
                product: {
                    id: 1,
                    accountTypeId: 1,
                    officeRangeId: 1,
                    additionalInfo: "",
                    enabled: true
                },
            };
            //act
            const newState = formsReducer(initialState, action);
            //assert
            expect(newState.blueprints).to.be.an('array');
            expect(newState.blueprints).to.equal(testBlueprints);
        }); 
    });
});

formsReducer.js:

import * as types from '../constants/actionTypes';
import objectAssign from 'object-assign';
import initialState from './initialState';
import formsHelper from '../utils/FormsHelper';
export default function formsReducer(state = initialState.forms, action) {
  switch (action.type) {
    case types.UPDATE_PRODUCT: {
        let formBlueprints = formsHelper.getFormsByProductId(action.product.id);
        formBlueprints = formsHelper.addOrRemoveMnDisclosure(formBlueprints, action.stateOfResidence.id);
        return objectAssign({}, state, {blueprints: formBlueprints, instances: []});
    }
}

formsHelper.getFormsByProductId is not returning testBlueprints as it should if it were properly stubbed via proxyquire. What am I doing wrong?

kibowki
  • 4,206
  • 16
  • 48
  • 74
  • I have a feeling it is because of the `.default` when you load it. Are you transpiling your test code with babel? Can you edit your question to include the header section with your requires/imports? Also, you can try `./node_modules/.bin/mocha --compilers js:babel-core/register` as your npm test script. – Mario Tacke Sep 19 '16 at 22:27
  • Hi Mario, I use the `.default` because if I don't, `.load('./formsReducer')` returns the following (which is not a function - I used `console.log` to get this): `{ default : [Function: formsReducer] }` - when I tried to use this as a function in the test I got an error. I have edited my question to include requires and imports as you requested - see if that helps you diagnose the problem further. – kibowki Sep 20 '16 at 13:44

1 Answers1

0

formsReducer.js is importing ../utils/FormsHelper, but proxyquire is trying to replace formsHelper. Try changing the proxyquire to:

proxyquire.noCallThru().load('./formsReducer', {
  '../utils/FormsHelper': {
    getFormsByProductId: id => { return testBlueprints }
  }
})
David Knipe
  • 3,417
  • 1
  • 19
  • 19
  • This worked when I used `../utils/FormsHelper` rather than the lower case version. However, it required me to create a stub for `formsHelper.addOrRemoveMnDisclosure` as well - if I didn't, I got the following error: `TypeError: _FormsHelper2.default.addOrRemoveMnDisclosure is not a function` - this appears to be a babel error of some sort? In the `proxyquire` documentation, it states that I should only have to replace the keys that I want to and ones that I don't replace keep their original functionality. – kibowki Sep 20 '16 at 14:03
  • You're right, I mistyped the filepath. I've fixed it now. I think the docs mean that you can proxyquire some files while leaving others unchanged. You could do `proxyquire.noCallThru().load('./formsReducer', { '../utils/FormsHelper': { getFormsByProductId: id => { return testBlueprints }, addOrRemoveMnDisclosure: require('../utils/FormsHelper').addOrRemoveMnDisclosure } });`. – David Knipe Sep 20 '16 at 22:47