Sinon: スタンドアロンのユーティリティ関数をスタブ化することは可能ですか?

作成日 2014年09月12日  ·  18コメント  ·  ソース: sinonjs/sinon

多くのノードモジュールは、単一の関数(コンストラクター関数ではなく、汎用の「ユーティリティ」関数)を「module.exports」としてエクスポートします。 Sinon.jsを使用してこのスタンドアロン関数をスタブ化することは可能ですか?

// 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();
});
...

これを達成する方法はありますか?

最も参考になるコメント

これを試して

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

全てのコメント18件

残念ながら違います。

npmの場合は、 https://github.com/thlorenz/proxyquireなどを使用できます。 Michael Feathersは、これをリンクシームと呼びます。

エレガントではありませんが、実行可能です。

それが整ったら、通常どおりにSinonを使用できます。

長期的には、アーキテクチャを_object seams_に移行したいと思うかもしれませんが、それは今日機能するソリューションです。 RequireJSにも同様のプロジェクトがあります。

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

次に、require( './ MyFunction')。MyFunctionをスタブ化できます。コードの残りの部分は、変更なしでスタブ化されたエディションを参照します。

:dizzy :: dizzy_face :: dizzy:

先日同じことを偶然見つけました、これが私がしたことです:

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

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

私たちの場合はかなりうまくいきます。

CommonJSを使用している場合:

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

_注_:トランスパイルするかどうかによって、次のことを行う必要があります。

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

多くの場合、テスト中に、1つの特定のテストに対して1つのスタブを挿入する必要があります。 私が採用したラッパー関数アプローチでは、コードベースを変更し、必要なときにいつでもスタブを挿入できます。スタブファーストのアプローチを採用したり、他のモジュールへの参照を持つモジュールでモグラたたきをしたりする必要はありません。スタブとその場での交換。

私は、proxyquire、 mock-require 、&​​cを介して、ノードモジュールレイヤーでのハッキングに向けて人々が私をプッシュするコードレビューを何度も受けました。それは単純に始まり、それほど粗雑ではないように見えますが、スタブを取得するのは非常に難しい課題になりますテストのセットアップ中に所定の位置に配置する必要があります。 proxyquireを使用すると、少なくとも1つはアプリのマイクロ/フィクスチャサイズのバージョンをproxyquire()できます。これはトップレベルであり、すべてのスタブはロード中に取り込まれますが、ノードモジュールレベルではなくJS言語レベルでこれに取り組みます。非常に簡単で、一貫して危険を伴わずに管理しやすいと思います(注意:復元することを覚えている限り)。

このモジュールをより簡単にスタブモジュールにするためにhttps://github.com/caiogondim/stubbable-decorator.js

私はちょうどシノンで遊んでいて、機能しているように見える簡単な解決策を見つけました-2番目の引数として「引数」を追加するだけです

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

これを試して

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

@ harryi3t-私のために働いてくれてありがとう。

@ harryi3t ESモジュールを使用して、それは私にとってはうまく
エラー: can't redefine non-configurable property "default"

@elliottregan ESモジュールは、標準に従ってスタブ化できません。 この動作ここで説明するようます

多くの人が実際にESモジュールをテストしているのではなく、(Webpack / Babelなどを使用して)トランスパイルされたESモジュールをテストしています。 結果のES5は、ゲッターを使用してESモジュールの動作をエミュレートします。 あなたはそれをしているかもしれませんが、リンクされたスレッドで私が提案する簡単なルートを試してください。 mocha --register ...はあなたに長い道のりをもたらします。

考えられる回避策

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

@Sujimoshi正確には何の回避策ですか? 修正のコンテキストは何ですか? また、人々はどこに修正を加えますか? 現在の化身では、役立つ情報が少し不足しています。 元の質問には役立たず、 ESモジュールでは機能しません。 これは、Webpack 4によって処理されたコードに関係していると思います。これは、ES5に_変換_されたES2015 +構文を使用して記述されたコードに適用される可能性があり、構成不可能なオブジェクト記述子を介してESモジュールの不変性を_エミュレート_するためです。 。

これを試して

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

現在非推奨です。

私はこれからES6モジュールを書き直しました:

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

これに:

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

少し不格好ですが、関数をスタブでラップすることができました。

今はほぼ2021年です、それは可能ですか?

今はほぼ2021年です、それは可能ですか?

2019年と大差ありません。
ESモジュールは変更されておらず、CommonJSも変更されておらず、JavaScriptも変更されていません。

このページは役に立ちましたか?
0 / 5 - 0 評価