Sinon: Possible de stub une fonction utilitaire autonome?

Créé le 12 sept. 2014  ·  18Commentaires  ·  Source: sinonjs/sinon

De nombreux modules de nœud exportent une seule fonction (pas une fonction constructeur, mais une fonction "utilitaire" à usage général) en tant que son "module.exports". Est-il possible d'utiliser Sinon.js pour stub cette fonction autonome ?

// some module, "sum.js" that's "required" throughout the application
module.exports = function(a, b) {
    return a + b;
};

// test.js
var sum = require('sum');
...

beforeEach(function() {
    sumStub = sinon.stub(sum);
    // throws: TypeError: Attempted to wrap undefined property undefined as function
});

afterEach(function() {
   sumStub.restore();
});
...

Y'a-t-il une quelconque façon de réussir cela?

Commentaire le plus utile

Essaye ça

import * as sum from './sum'
sinon.stub(sum, 'default', () => {
  // stubbed function
});

Tous les 18 commentaires

Malheureusement non.

Pour npm, vous pouvez utiliser https://github.com/thlorenz/proxyquire ou similaire. Michael Feathers appellerait cela une couture de liens .

Ce n'est pas élégant, mais faisable.

Une fois que vous avez cela en place, vous pouvez utiliser Sinon comme vous le feriez normalement.

À long terme, vous voudrez peut-être déplacer votre architecture vers des coutures d'objets, mais c'est une solution qui fonctionne aujourd'hui. Des projets similaires existent pour RequireJS.

function MyFunction(){}
module.exports = function(){ return module.exports.MyFunction.apply(this, arguments) }
module.exports.MyFunction = MyFunction

Ensuite, vous pouvez stub require('./MyFunction').MyFunction et le reste de votre code verra sans changement l'édition stub.

:dizzy: :dizzy_face: :dizzy:

Je suis tombé sur la même chose l'autre jour, voici ce que j'ai fait :

const proxyquire = require('proxyquire')
const sinon = require('sinon')
const sum = sinon.stub()

const ModuleWithDependency = proxyquire('module', {
  'sum': sum
})

fonctionne assez bien pour notre cas.

Si vous utilisez CommonJS :

const myStubbedModule = function( absoluteModulePath ) {
  const stub = sinon.stub();
  require.cache[ require.resolve( absoluteModulePath ) ] = stub;
  return stub;
}

_Remarque_ : Selon que vous transpilez ou non, vous devrez peut-être faire :

require.cache[ require.resolve( absoluteModulePath ) ] = {
  default: stub,
  exports: stub
}

Souvent, pendant les tests, je devrai insérer un talon pour un test spécifique. L' approche de la fonction wrapper que j'ai

J'ai eu un certain nombre de revues de code où les gens m'ont poussé à pirater la couche du module Node, via proxyquire, mock-require , etc. nécessaire en place lors de la configuration du test. Avec proxyquire, au moins un proxyquire() peut être une version de l'application de la taille d'un micro/appareil, quelque chose de haut niveau, et tous les stubs seront introduits pendant son chargement, mais s'attaquer à cela au niveau du langage JS plutôt qu'au niveau du module Node continue pour me sembler nettement plus simple et plus facile à gérer de manière cohérente et sans danger (mise en garde : tant que l'on se souvient de restaurer).

J'ai fait ce module pour stub plus facilement les modules https://github.com/caiogondim/stubbable-decorator.js

Je jouais juste avec Sinon et j'ai trouvé une solution simple qui semble fonctionner - ajoutez simplement "arguments" comme deuxième argument

const sumStub = sinon.stub(sum, 'arguments');
sumStub.withArgs(2, 2).returns(4);
sumStub.withArgs(3, 3).returns(6);

Essaye ça

import * as sum from './sum'
sinon.stub(sum, 'default', () => {
  // stubbed function
});

@harryi3t - merci cela a fonctionné pour moi.

@harryi3t Cela n'a pas fonctionné pour moi, en utilisant les modules ES.
Erreur : can't redefine non-configurable property "default"

Les modules même des tests couvrant ce comportement. Vous pouvez toujours le faire, cependant, comme je le

Beaucoup de gens ne testent pas réellement les modules ES, mais les modules ES transpilés (en utilisant Webpack/Babel, etc.). L'ES5 résultant utilise des getters pour émuler le fonctionnement des modules ES. Vous faites peut-être cela, mais essayez la route simple que je suggère dans le fil lié. mocha --register ... vous emmène loin.

Solution de contournement possible

(function (defineProperty) {
    Object.defineProperty = (obj, prop, desc) => {
        desc.configurable = true;
        return defineProperty(obj, prop, desc);
    };
})(Object.defineProperty);

@Sujimoshi Solution de contournement pour quoi exactement ? Quel est le contexte de votre correctif ? De plus, où les gens mettraient-ils le correctif ? Dans son incarnation actuelle, il manque un peu trop d'informations pour être utile. Cela n'aiderait pas la question d'origine et ne fonctionnerait pas pour les modules ES . Je suppose que cela concerne le code qui a été traité par Webpack 4, car il pourrait s'appliquer (selon votre chaîne d'outils) au code écrit à l'aide de la syntaxe ES2015+ qui a été _transpilé_ dans ES5, _émulant_ l'immuabilité des modules ES via des descripteurs d'objets non configurables .

Essaye ça

import * as sum from './sum'
sinon.stub(sum, 'default', () => {
  // stubbed function
});

obsolète maintenant.

Je viens de réécrire mon module ES6 à partir de ceci :

export default const doCoolStuff = () => {
  // do the cool stuff...
}

pour ça:

export default {
  doCoolStuff: () => {
    // do the cool stuff...
  }
} 

C'est un peu maladroit, mais m'a permis d'envelopper la fonction dans un talon.

nous sommes maintenant presque en 2021, est-ce possible?

nous sommes maintenant presque en 2021, est-ce possible?

Pas très différent de 2019.
Les modules ES n'ont pas changé, CommonJS n'a pas changé, JavaScript n'a pas changé.

Cette page vous a été utile?
0 / 5 - 0 notes