web-dev-qa-db-fra.com

Comment stub fonction exportée dans ES6?

J'ai le fichier foo.js:

export function bar (m) {
  console.log(m);
}

Et un autre fichier qui utilise foo.js, cap.js:

import { bar } from 'foo';

export default m => {
  // Some logic that I need to test
  bar(m);
}

J'ai test.js:

import cap from 'cap'

describe('cap', () => {
  it('should bar', () => {
      cap('some');
  });
});

D'une manière ou d'une autre, j'ai besoin de remplacer l'implémentation de bar(m) dans le test. Y a-t-il un moyen de faire ça?

P.S. J'utilise babel, webpack et moka.

41
Mike Chaliy

Ouch .. J'ai trouvé la solution, donc j'utilise sinon pour stub et import * as foo from 'foo' pour obtenir un objet avec toutes les fonctions exportées afin que je puisse les stub. 

import sinon from 'sinon';
import cap from 'cap';
import * as foo from 'foo';

sinon.stub(foo, 'bar', m => {
    console.log('confirm', m);
});

describe('cap', () => {
  it('should bar', () => {
    cap('some');
  });
});
48
Mike Chaliy

Vous pouvez remplacer/réécrire/exporter des copies uniquement à partir du module lui-même. (Voici une explication )

Si vous réécrivez 'foo.js' comme ceci:

var bar = function bar (m) {
  console.log(m);
};

export {bar}

export function stub($stub) {
  bar = $stub;
}

Vous pouvez ensuite le remplacer dans votre test comme ceci:

import cap from 'cap'
import {stub} from 'foo'

describe('cap', () => {
  it('should bar', () => {
      stub(() => console.log('stubbed'));
      cap('some'); // will output 'stubbed' in the console instead of 'some'
  });
});

J'ai créé un plugin Babel qui transforme automatiquement toutes les exportations afin qu'elles puissent être écrites: https://github.com/asapach/babel-plugin-rewire-exports

7
DreamSonic

Bien que la solution @Mike fonctionne dans les anciennes versions de sinon, elle a été supprimée depuis sinon 3.0.0. 

Maintenant au lieu de:

sinon.stub(obj, "meth", fn);

tu devrais faire:

stub(obj, 'meth').callsFake(fn)

Exemple de google oauth api moqueur:

import google from 'googleapis';

const oauth2Stub = sinon.stub(); 

sinon.stub(google, 'oauth2').callsFake(oauth2Stub);

oauth2Stub.withArgs('v2').returns({
    tokeninfo: (accessToken, params, callback) => {
        callback(null, { email: '[email protected]' }); // callback with expected result
    }
});
2
Daniel Conde Marin

Vous pouvez utiliser babel-plugin-rewire (npm install --save-dev babel-plugin-rewire)

Et ensuite, dans test.js, utilisez la fonction __Rewire__ sur le module importé pour remplacer la fonction dans ce module:

// test.js
import sinon from 'sinon'

import cap from 'cap'

describe('cap', () => {
  it('should bar', () => {
    const barStub = sinon.stub().returns(42);
    cap.__Rewire__('bar', barStub); // <-- Magic happens here
    cap('some');
    expect(barStub.calledOnce).to.be.true;
  });
});

Assurez-vous d’ajouter rewire à vos plugins babel dans .babelrc:

// .babelrc
{
  "presets": [
    "es2015"
  ],
  "plugins": [],
  "env": {
    "test": {
      "plugins": [
        "rewire"
      ]
    }
  }
}

Enfin, comme vous pouvez voir que le plug-in babel-plugin-rewire est uniquement activé dans l'environnement de test, vous devez appeler votre testeur avec la variable d'environnement BABEL_ENV définie sur test (ce que vous êtes probablement déjà en train de faire):

env BABEL_ENV=test mocha --compilers js:babel-core/register test-example.js

Note: Je n'ai pas pu faire fonctionner babel-plugin-rewire-exports.

1
qff