mardi 6 mars 2018

Can ES6 constructors be stubbed more easily with Sinon?

Given the (overly simplified) snippet:

import Validator from 'validator';

export default function isValid(arg) {
  // Validator#isValid is an ES6 getter
  return new Validator(arg).isValid;
}   

How can I test that a Validator was instantiated with the given parameter? And stub isValid?


I know I can restructure my code to avoid the issue, I am not looking for a workaround as I found plenty (dependency injection, not using ES6 sugar, etc.).

I found a way, but it is terribly ugly. In test file:

import ValidatorNamespace from 'validator';

const Validator = ValidatorNamespace.default;
let validatorInstance;
let validatorConstructor;

const subject = arg => isValid(arg);
const validityStatus = true;

describe('isValid helper', () => {
  beforeEach(() => {
    validatorInstance = sinon.createStubInstance(Validator);

    // Yay! This is how I managed to spy on the constructor!.. :(
    validatorConstructor = sandbox.stub(ValidatorNamespace, 'default').
      returns(validatorInstance);

    sandbox.stub(validatorInstance, 'isValid').value(validityStatus);
  });

  it('instantiates the validator properly', ()=> {
    subject('arg');
    expect(validatorConstructor).to.have.been.calledWith('arg')
  });

  it('returns the value returned by the validator', ()=> {
    expect(subject('arg')).to.eq(validityStatus);
  });
});

Validator code:

export default class Validator {
  constructor(arg) {
    this.innerValue = arg;
  }

  get isValid() {
    return aFunctionOf(this.innerValue);
  }
}

Aucun commentaire:

Enregistrer un commentaire