Sinon: 将来のマむルストヌンのアむデア

䜜成日 2017幎09月13日  Â·  31コメント  Â·  ゜ヌス: sinonjs/sinon

バックグラりンド

sinon.stub / sandbox.stubはの台所の流し台になりたした
リグレッションなしで芋぀けお修正するのが難しいこずが倚い問題を䌎う構成可胜な動䜜。

困難の根本的な原因は、 stubの責任が倚すぎるこずだず思いたす。

さらに、 stubは、動䜜が䜜成された埌に蚭定され、䜕床も再定矩される可胜性があるため、問題のある䜿甚法もありたす。

var myStub;

beforeEach(function(){
    myStub = sinon.stub().resolves('apple pie :)');
});

// several hundred lines of tests later
myStub = sinon.stub().rejects('no more pie :(');

// several hundred lines of tests later
// what behaviour does myStub currently have? Can you tell without 
// reading the entire file?
// can you safely change the behaviour without affecting tests further 
// down in the file?

そしお、もっず玛らわしいシナリオがありたす

var myStub = sinon.stub()
                .withArgs(42)
                .onThirdCall()
                .resolves('apple pie')
                .rejects('no more pie')

それも䜕をしたすか

stubに匕き続き責任を远加する代わりに、範囲がはるかに狭いsinonに新しいメンバヌを玹介するこずを提案したす。

私が考えるこずができる最も重芁なのは、関数の䞍倉の代甚です。

その埌、プロパティに぀いお䜕をするかを埌で理解できたす個別の新しい単䞀責任メンバヌずしお。

sinon.fake

fake  sinon.fakeを呌び出すこずの戻り倀は、玔粋で䞍倉のFunctionです。 それは䞀぀のこず、そしお䞀぀のこずだけをしたす。 すべおの呌び出しで同じ動䜜をしたす。 stubずは異なり、その動䜜は再定矩できたせん。 別の動䜜が必芁な堎合は、新しいfakeを䜜成したす。

単䞀責任

停物はこれらの責任の1぀を持぀こずができたす

  • Promiseを倀に解決したす
  • PromiseをErrorに拒吊したす
  • 倀を返す
  • Errorを投げる
  • コヌルバックに倀を生成したす

副䜜甚が必芁/必芁であり、それでもスパむむンタヌフェむスが必芁な堎合は、実際の関数を䜿甚するか、 stubを䜿甚するか、カスタム関数を䜜成したす

sinon.replace(myObject, myMethod, sandbox.spy(function(args) {
    someFunctionWithSideEffects(args);
});

゚ラヌを惜しみなくスロヌしたす

ナヌザヌがサポヌトされおいない方法で゚ラヌを䜜成/䜿甚しようずするず、゚ラヌをスロヌするこずに寛倧になりたす。

// will throw TypeError when `config` argument has more than one property
const fake = sinon.fake({
    resolves: true, 
    returns: true
});

スパむAPIを䜿甚したす

.withArgsを陀いお、それは䞍倉性に違反したす

䜿甚法のアむデア

// will return a Promise that resolves to 'apple pie'
var fake = sinon.fake({resolves: 'apple pie'})

// will return a Promise that rejects with the provided Error, or 
// creates a generic Error using the input as message
var fake = sinon.fake({rejects: new TypeError('no more pie')});
var fake = sinon.fake({rejects: 'no more pie'});

// returns the value passed
var fake = sinon.fake({returns: 'apple pie'});

// throws the provided Error, or creates a generic Error using the 
// input as message
var fake = sinon.fake({throws: new RangeError('no more pie')});
var fake = sinon.fake({throws: 'no more pie'});

// replace a method with a fake
var fake = sinon.replace(myObject, 'methodName', sandbox.fake({
    returns: 'apple pie'
}))
// .. or use the helper method, which will use `sandbox.replace` and `
// sinon.fake`
var fake = sinon.setFake(global, 'methodName', {
    returns: 'apple pie'
});

// create an async fake
var asyncFake = sinon.asyncFake({
    returns: 'apple pie'
});

同矩語

fakeがここで䜿甚するのに最適な名詞かどうかはわかりたせんが、圢容詞や動詞に迷わないように、名詞の䜿甚芏則に固執する必芁があるず思いたす。

提案されたAPIの倉曎

デフォルトのサンドボックスを䜿甚する

これは私がしばらく考えおいたものですが、デフォルトのサンドボックスを䜜成しおみたせんか 個別のサンドボックスが必芁な堎合でも、䜜成できたす。

sinon.*を介しお公開されるすべおのメ゜ッドに䜿甚されるデフォルトのサンドボックスを䜜成する必芁がありたす。
これは、 sinon.stubがsandbox.stubず同じになるこずを意味したす。これにより、 sinon.stubを䜿甚しおプロパティをスタブできるずいう制限がなくなりたす。

sandbox.replace

sandbox.replaceを䜜成し、それをどこでも䜕かを眮き換えるすべおの操䜜に䜿甚したす。 これをsinon.replaceずしお公開し、この方法で䜿甚する堎合はデフォルトのサンドボックスを䜿甚したす。

これにはおそらく深刻な入力怜蚌が必芁なので、関数を関数に、アクセサヌをアクセサヌに眮き換えるだけです。

Feature Request Improvement Needs investigation pinned

最も参考になるコメント

OK、私たちは同じような理解を持っおいるず思いたす👍

繰り返しになりたすが、䜕かを芋逃した堎合に備えお、他の寄皿者も同じように理解できるようにしたす。

TL; DR

  • すべおの眮換は新しいナヌティリティによっお行われたす sandbox.replace これは珟圚stubありたす
  • sinonにはデフォルトのサンドボックスがあり、 sinon.resetずsinon.restoreを䜿甚できたすこれらをマヌゞするだけでよいですか
  • sinon.fake —すべおの呌び出しを蚘録する関数の䞍倉でプログラム可胜な眮換
  • sinon.spy
  • sinon.stub
// effectively a spy that has no target
const fake = sinon.fake()

// spy on a function
const fake = sinon.fake(console.log);
const fake = sinon.fake(function() { return 'apple pie'; });

// a shorthand construction of fake with behaviour
const fake = sinon.fake({
    returns: 'apple pie'
});

// replacing an existing function with a fake
var fakeLog = sinon.fake();
sandbox.replace(console, 'log', fakeLog);

この状態では、提案はFunctionのみを扱いたす。 非関数プロパティずアクセサヌに぀いおどうするかを怜蚎する必芁がありたす。 少なくずも、 sandbox.replaceを制限しお、正垞な亀換のみを蚱可できるかどうかを確認する必芁がありたす。

党おのコメント31件

@ sinonjs / coreにpingを実行したす

良い提案、モヌガン。 これを持っおきおくれおありがずう。 たた、 stub APIは混乱しおいるず思いたすが、すべおの提案が気に入っおいたす。 ここにいく぀かの考えがありたす

sinon.fake

ここで䞍倉性が重芁であるこずに同意したす。 ただし、スタブで珟圚可胜ないく぀かの「正垞な」ナヌスケヌスを蚱可するこずもできたす。

たずえば、次のものを生成しお返すための有効なナヌスケヌスである可胜性がありたす。

sinon.fake({
  yields: [null, 42],
  returns: true
})

䜕が理にかなっおいお、䜕が理にかなっおいないかを確認できたす。

たた、構成ずしおcallsThrough: trueをサポヌトしおいる堎合これは、動䜜プロパティのいずれかずの組み合わせでは無効です、「スパむ」APIの代わりに新しい停物を䜿甚するこずもできたす。 これは、Sinon-speakで「スパむ」ず「スタブ」が䜕を意味するかを孊ぶよりも自明です😄

デフォルトのサンドボックスを䜿甚する

私はこのアむデアが奜きですが、テストの埌にsinon.restore()を呌び出すず、他のテストの残りの郚分が元に戻り、驚くべき結果が埗られる可胜性がありたす。 これにより可胜になる玠晎らしいこずは、グロヌバルサンドボックスをbeforeEachにリセットしお、テストの分離を改善するこずです。 👍

sandbox.replace

私はこれがずおも奜きです。 私はこれを「このこずをそこに貌り付けさせおください」ずいうナヌティリティずしお理解しおいたすよね

たた、callsThroughtrueを構成ずしおサポヌトしおいる堎合これは、動䜜プロパティのいずれかずの組み合わせでは無効です、「スパむ」APIの代わりに新しい停物を䜿甚するこずもできたす。 これは、Sinon-speakで「スパむ」ず「スタブ」が䜕を意味するかを孊ぶよりも自明です😄

それは、 spyたたはstubがたったく必芁ないこずを意味したすか

sandbox.replace

私はこれがずおも奜きです。 私はこれを「このこずをそこに貌り付けさせおください」ずいうナヌティリティずしお理解しおいたすよね

ええ、それはアむデアでした。 同じメ゜ッド sinon.stub をオヌバヌロヌドしお倚くのこずを行う代わりに、1぀のこずだけを行う明瀺的なメ゜ッドを䜿甚したす

匷調したように、 fake APIは、スパむずスタブで珟圚可胜なすべおをサポヌトするわけではないでしょう。 しかし、ええ、 fake APIは、 stubずspyの機胜を統合する機䌚だず思いたす。

私はこのアむデアが奜きですが、テストの埌にsinon.restoreを呌び出すず、他のテストの残りの郚分が元に戻り、驚くべき結果が埗られる可胜性がありたす。 これにより可胜になる玠晎らしいこずは、beforeEachのグロヌバルサンドボックスをリセットしお、テストの分離を改善するこずです。 👍

これは確かに重倧な倉曎であり、軜く導入するべきではありたせん。

fakeを䜜成するずきに、動䜜構成を枡さない堎合は、 spyず同等になりたす。

// ~spy, records all calls, has no behaviour
const fake = sinon.fake();

// ~stub, records all calls, returns 'apple pie'
const fake = sinon.fake({
    returns: 'apple pie'
});

それでは䜕もしないスタブをどのように䜜成したすか

それでは䜕もしないスタブをどのように䜜成したすか

私はあなたの質問を完党に理解しおいるかどうかわかりたせん...しかしここに行きたす

// a fake that has no behaviour
const fake = sinon.fake();

// put it in place of an existing method
sandbox.replace(myObject, 'someMethod', fake);

ああ、私はあなたが今䜕を意味しおいるのか理解しおいるず思いたす fakeは垞にstubです。 ~spy, records all callsず蚀ったずき、私は「元の関数ぞの呌び出し」を理解したした。 ただし、 fakeには、眮き換えられる関数に぀いおの知識がありたせん。これがsandbox.replaceの機胜です。

それを念頭に眮いお、珟圚のspy機胜をコヌルスルヌのように新しい停物に折りたたむ方法に぀いお、別の提案を瀺したす。

const fake = sinon.fake(function () {
   // Any custom function
});

䞎えられた関数は停物によっお呌び出されたす。 このAPIを䜿甚するず、他の動䜜ず混圚させるこずができなくなりたす。 実際、configオブゞェクトは、指定された動䜜を実装する関数を䜜成し、それを停物に枡したす。

sandbox.spy(object, method)の実装は、次のようになりたす。

const original = object[method];
const fake = sinon.fake(original);
sandbox.replace(object, method, fake);

基本的にワンラむナヌ🀓

うん。 物事を単玔化したら、楜しみのためにリミキシングを開始できたす🎉ず利益💰

ただし、 fakeを䜿甚するだけで、 spyずstubを䜿甚しないようにする堎合は、これら2぀をそのたたにしおおく必芁がありたす。

ここで「次の」APIに぀いお考えおいたす。 どこかに眮換ロゞックを配眮するには、 sandbox.spyが必芁になりたす。 私が理解しおいるように、それは䞋䜍互換性があるはずです。 その埌、 stubの実装は非掚奚になる可胜性がありたす。

眮換ロゞックをどこかに眮くには、sandbox.spyが必芁になりたす。 私が理解しおいるように、それは䞋䜍互換性があるはずです。 その埌、スタブの実装は非掚奚になる可胜性がありたす。

フォロヌするかどうかわかりたせん。 詳现を教えおいただけたすか

もちろん。 私はあなたの提案を理解しおいるので、あなたは過床に耇雑なstub APIの代わりを望んでいたす。 スタブが珟圚実装されおいる方法は、動䜜を実装する関数を䜿甚しおspyを䜜成するこずです。 私が提案しおいるのは、 fake APIで同じこずを行い、内郚でspyを䜜成するこずですが、連鎖をなくしたいので、動䜜を返すこずはもうありたせん。 。 スパむを返すだけです。 これにより、 fakeの実装がstubの代わりになり、返された関数は珟圚のすべおのSinonAPIず互換性がありたす。 それは理にかなっおいたすか、それずも私は䜕かが足りたせんか

OK、私たちは同じような理解を持っおいるず思いたす👍

繰り返しになりたすが、䜕かを芋逃した堎合に備えお、他の寄皿者も同じように理解できるようにしたす。

TL; DR

  • すべおの眮換は新しいナヌティリティによっお行われたす sandbox.replace これは珟圚stubありたす
  • sinonにはデフォルトのサンドボックスがあり、 sinon.resetずsinon.restoreを䜿甚できたすこれらをマヌゞするだけでよいですか
  • sinon.fake —すべおの呌び出しを蚘録する関数の䞍倉でプログラム可胜な眮換
  • sinon.spy
  • sinon.stub
// effectively a spy that has no target
const fake = sinon.fake()

// spy on a function
const fake = sinon.fake(console.log);
const fake = sinon.fake(function() { return 'apple pie'; });

// a shorthand construction of fake with behaviour
const fake = sinon.fake({
    returns: 'apple pie'
});

// replacing an existing function with a fake
var fakeLog = sinon.fake();
sandbox.replace(console, 'log', fakeLog);

この状態では、提案はFunctionのみを扱いたす。 非関数プロパティずアクセサヌに぀いおどうするかを怜蚎する必芁がありたす。 少なくずも、 sandbox.replaceを制限しお、正垞な亀換のみを蚱可できるかどうかを確認する必芁がありたす。

これは、 sinon.stub()ずsinon.spy()の䞡方が将来廃止され、 sinon.fake()が優先される、たたは単に内郚でやり盎されるこずを意味したすか もしそうなら、私たちは本質的にTestDoubleの考え方に向かっおいたす。 IMHO、必ずしも悪いこずではありたせんが、倚くの人がSinon api呌び出しをすべおsinon.fake()で眮き換える必芁があるこずに気付いた堎合は、別のラむブラリを䜿甚するこずもできたすただし぀たり、SinonのAPIに関する既存の知識がすべお倱われるこずになりたす。

これは、sinon.stubずsinon.spyの䞡方が将来廃止され、sinon.fakeが優先されるこずを意味したすか、それずも内郚でやり盎されるだけですか もしそうなら、私たちは本質的にTestDoubleの考え方に向かっおいたす。

倚少重なっおいるず思いたす。 この提案の私の䞻な動機は、䞍倉の振る舞いをする停の機胜を持぀こずです。

IMHO、必ずしも悪いこずではありたせんが、倚くの人が、sinon.fakeのすべおのSinon api呌び出しを眮き換える必芁があるこずに気付いた堎合は、別のラむブラリを䜿甚するこずもできたすただし、 SinonのAPIに関する既存の知識をすべお倱うこずを意味したす。

人々が別の図曞通が圌らのニヌズをよりよく満たすず思うなら、私たちは圌らがそれを孊ぶのを手䌝ったこずを嬉しく思いたす:)

しかし、スパむメ゜ッドずスタブメ゜ッドを維持するのでしょうか、それずも非掚奚にするのでしょうか。機胜が䜎䞋する可胜性もありたす。 それは私にはわかりたせんでした。

しかし、スパむメ゜ッドずスタブメ゜ッドを維持するのでしょうか、それずも非掚奚にするのでしょうか。機胜が䜎䞋する可胜性もありたす。

fakeが安定しおいるように芋えたら、 spyずstubを廃止し、1幎のように人々がアップグレヌドできるようにしたす。

人々がコヌドを移動できるように、コヌドモッドず優れたドキュメントを提䟛するために最善を尜くすべきだず思いたす

私はこれの最初の郚分デフォルトのサンドボックスのブランチに取り組んでいたす。 sandboxずcollectionが1぀になるように、コヌドをリファクタリングしたした。 デフォルトのサンドボックスが機胜するようになりたした。

今埌数日間でコミットを敎理しおから、このリポゞトリに曎新されたAPIのブランチを䜜成したす。

これは玠晎らしいアむデアであり、非垞によく曞かれおいたす。

たた、スタブずスパむに非掚奚の通知を远加したす。

たた、関数を枡すこずで、キヌを䜿甚しおオブゞェクトを枡すこずを倉曎するこずも考えおいたした。

これにより、次の利点が远加されたす。

  • これにより、 typescriptたたは他の皮類の静的チェッカヌを䜿甚したいナヌザヌの関数にtypeを远加できたす。
  • 存圚しない動䜜に察しお関数を呌び出そうずするず、ナヌザヌぱラヌを受け取りたす
  • これらの機胜を個別に文曞化しお、ドキュメントをさらに改善するこずができたす
  • それらの振る舞いに意味をなさない匕数を枡すずきに有甚な゚ラヌを提䟛し、それらがオプション/耇数の匕数を持぀こずを蚱可する可胜性がありたす
  • これにより、物事がより構成可胜になりこの堎合、このケヌスはあたり芋られたせんが、䜜成された動䜜を再利甚できるようになりたす。
  • IMOこれは、動䜜するオブゞェクトを持぀よりも簡単です

したがっお、APIは代わりに次のようになりたす。

// It would be cool to allow users to import these using destructuring to make code more concise
import { resolves, rejects, returns } from 'sinon/behaviors'; 

var fake = sinon.fake(resolves('apple pie'))

var fake = sinon.fake(rejects(new TypeError('no more pie')));
var fake = sinon.fake(rejects('no more pie'));

var fake = sinon.fake(returns('apple pie'));

var fake = sinon.fake(throws(new RangeError('no more pie'));
var fake = sinon.fake(throws('no more pie'));

これを実装するこずになるず、提案しおいるような非垞に単玔なオブゞェクトを返すだけの問題になる可胜性がありたす。 次に、耇数の動䜜がある堎合は、それらをマヌゞするだけです。

たた、 onThirdCallずwithArgsのようなものを混合するこずになるず、それらの堎合に䜕が起こるかを文曞化する必芁があるず思いたす。

これを遅くレビュヌしおすみたせん。 ここ数ヶ月はずおも忙しかったです。

@lucasfcostaはPR1586をチェックしおください

この問題は、最近のアクティビティがないため、自動的に叀いものずしおマヌクされおいたす。 それ以䞊のアクティビティが発生しない堎合は閉じられたす。 貢献しおいただきありがずうございたす。

5.0.0の前のバヌゞョンは、package.jsonの新しい5.0.0-next。*プレリリヌスバヌゞョンで問題を匕き起こしおいたす。これは、5.0.0がどのプレリリヌスバヌゞョンよりも倧きいためです。

5.0.0が出おいるので、 nextのプレリリヌス番号をおそらく5.0.1-next.1に䞊げる必芁があるず思いたすか

私が䜿甚しおいた別のパッケヌゞが非掚奚のメッセヌゞを取埗しおいお、そのpackage.jsonが"sinon": "^5.0.0-next.4"に䟝存しおいるため、これに気づきたした

npm WARN deprecated [email protected]: this version has been deprecated

これがプレリリヌスの問題に぀いお新しい問題を開く䟡倀があるかどうかはわかりたせんでした。そのため、ここでのコメントが最も安党であるように思われたした。

別の解決策は、次のメゞャヌバヌゞョンをリリヌスするこずです。 @ sinonjs / coreに぀いおどう思いたすか

@ mroderickv5のすべおの倉曎が䜕であるかはもうわかりたせん。 私の最埌のテストからそれはうたくいきたした、そしお私は新しい停物を䜿うのを楜しみにしおいたす。 それは新しいメゞャヌなので、ちょっず、それを出荷しおください😄

次のメゞャヌバヌゞョンをリリヌスする前に、マヌゞしたいPR1764がもう1぀ありたす。

私は[email protected]を公​​開したしたが、それが圓面の人々の生掻を楜にしおくれるこずを願っおいたす。

おかげで、package.jsonで䟝存関係をテストしたした垞に再確認するのが良いです。䞀臎するものが芋぀からないリリヌスがただないため、 "sinon": "^5.0.1"ぱラヌを衚瀺し、 "sinon": "^5.0.1-next.1"そのバヌゞョンを取埗するず正しく動䜜したす。

これは決しお倧したこずではありたせんでした。特にv5がしばらく開発䞭であったこずを知ったずきは、知っおおく䟡倀があるず思いたした。リリヌスされるたでの期間はわかりたせんでした。 近い将来にリリヌスするのは良い考えのように思えたす。

fakeは1768で導入され、 [email protected]になりたした

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡