#1512に関連。
プロパティが存在しない場合は、サンドボックスに追加する必要はありません。 単に上書きします。 しかし、ええ、それが以前に機能し、それが変更されるべきであると明示的に述べていない場合、それは回帰です。
ここで何をすべきかわからない。 ドキュメントを更新して、存在しない値をスタブすることは意味がなく、サポートされていない、またはそれを可能にするようにしますか?
プロパティが存在しない場合は、サンドボックスに追加する必要はありません。 単に上書きします。
プロパティをサンドボックスに追加することの良い点は、sinonが、 sandbox.restore()
介して各テスト間でグローバルテスト環境をクリーンに保つのに役立つことです。 これは非常に便利な機能です。特に、APIを制御していないGoogleマップのようなサードパーティのライブラリを扱う場合に便利です。 3.xラインで動作させることができれば素晴らしいと思います。
また、完全な例を提供しないという罪を犯したことに気づきました。 私のサンドボックスは2.4.1形式で作成されています:
let sandbox;
before(() => { sandbox = sinon.sandbox.create(); })
afterEach(() => { sandbox.restore(); })
それが重要かどうかはわかりません。 早く提供しなかったことをお詫びします。
@ZebraFleshが説明しているようなシナリオでは、テキストフィクスチャをより明示的にしたいと思います。
// not so explicit, doesn't work with [email protected]
beforeEach(function() {
const spy = sandbox.spy();
sandbox.stub(window, 'google').value({
maps: {
LatLng: x => x,
Map: spy
}
});
});
// more explicit, works with sinon<strong i="9">@2</strong>, sinon<strong i="10">@3</strong>
function setGoogleMapsFixture(sandbox) {
window.google = {
maps: {
LatLng: x => x,
Map: sandbox.spy()
}
};
}
function removeGoogleMapsFixture() {
delete window.google;
}
beforeEach(function() {
setGoogleMapsFixture(sandbox)
});
// not using afterEach, as this only needs to happen
// after the last test in this block is run
after(function() {
removeGoogleMapsFixture();
});
上で概説したようなフィクスチャのより明示的な設定では、存在しない独自のプロパティのスタブを可能にするSinonの機能は必要ありません。
ここで何をすべきかわからない。 ドキュメントを更新して、存在しない値をスタブすることは意味がなく、サポートされていない、またはそれを可能にするようにしますか?
一部のシナリオ(@ZebraFleshで説明されているシナリオなど)では便利な場合があることは認識していますが、存在しない独自のプロパティをスタブすると、テストでミスが発生する可能性が高いと思います。彼らがスタブすることを目指していた既存のプロパティ。 制限しすぎずに、できる限り間違いの可能性を排除することを目指すべきです。
存在しない独自のプロパティをスタブすることはサポートされないままである必要があると思います。 ドキュメントを更新する必要があります。
@mroderickバグが少なくなる可能性があるという点で同意しますが、通常のスタブではすでにこれをサポートしています。 この動作のサポートを停止する必要がある場合は、一貫性を保つために、そこでも削除する必要があります。 サンドボックスは通常いくつかの可能性を追加するため、サンドボックスの外部でのみこの機能をサポートするのは奇妙なことです。 また、サポートを削除することは破壊的な機能であるため、大きなバンプも必要になります。
だからどちらか:
または(?)
上で概説したようなフィクスチャのより明示的な設定では、存在しない独自のプロパティのスタブを可能にするSinonの機能は必要ありません。
あなたのフィクスチャがあなたのテスト間で決して変化しないならば、それはうまくいくと思います。 しかし、私のフィクスチャはそうします。 簡単な例は、成功と失敗の両方のケースをカバーすることです。
it('handles the success case', () => {
const spy = sandbox.spy();
sandbox.stub(window, 'google').value({
maps: {
LatLng: x => x,
Map: spy
}
});
// ... test, including asserting that the spy was called
});
it('handles the failure case', () => {
const msg = 'test error';
sandbox.stub(window, 'google').value({
maps: {
LatLng: x => x,
Map: sandbox.stub().throws(new Error(msg))
}
});
// ... test, ignoring spy calls and instead focusing on error handling
});
2.xの動作には、 sandbox.restore()
介して各テスト後にすべてが適切にクリーンアップされるという利点があります。 上で概説したより明示的なフィクスチャ設定の例を使用して、同じ効果を達成するためにafterEach
フックの非所有プロパティを削除できると思います。
既存の独自のプロパティの名前を誤って入力して潜在的な間違いを引き起こす問題を解決するために、sinonはパブリックAPIを変更する可能性があります。
stub.ownValue()
:スタブはプロパティのみを所有し、所有していないプロパティをスローしますstub.value()
:所有していないプロパティのみをスタブし、独自のプロパティをスローしますAPIはより明確になり、消費者は目前のタスクに適切なツールを選択することを余儀なくされます。
これは、#1508(通常のスタブを扱っていますが)hでの議論に非常に関連しています。ここで、 @ lucasfcostaは反対の見方をしています。つまり、 undefined
プロパティに対しては_投げるべきではありません_。 何に着手しても、通常のスタブとサンドボックスのスタブAPIでは_一貫性が必要である_と強く信じています。 ある場合にはそれをサポートすべきではなく、他の場合にはサポートすべきではありません。
現在の状況は次のとおりです。
そのため、しばらくの間、機能の同等性がありましたが、その後再び失われました...このジグザグはユーザーにとってあまり有益ではないと思うので、この議論を開始する必要があります。 より具体的なテストが行われる可能性があるという点でMorganに同意しますが、2つのメジャーリリースの動作を削除してから再度追加するのは好きではありません。 このリグレッションを元に戻すだけで、ノイズ(クライアントの修正、このトラッカーの質問/問題)が最小になると思います。
不便さは理解していますが、コードの変更を最小限に抑えて簡単に回避できるようです。
before(function() {
window.google = 'This is a placeholder for sinon to overwrite.';
});
after(function() {
delete window.google;
});
これにより、sinonコードを変更しないでおくことができます。
テストがあるため、これは予想される動作のようです。 私の意見にそれを反映するためにドキュメントを更新する必要があります。 それはメジャーで来たので、破壊的な変更は許容されます。
@fearphage現状を維持するということは、存在しないフィールドをスタブすることはサンドボックスではサポートされていない動作ですが、通常のスタブではサポートされている動作であることを意味します。 2つの機能セットが一致しないのは少し残念ではありませんか?
解決は#1557で実装されました
さまざまなスレッドを読んで、なぜこれが起こったのかがわかりますが、クラスプロトタイプに実装された関数を頻繁に使用するタイプスクリプトでは、本当に苦痛です。その場合、すべてが正常に見えるにもかかわらず、sinonがダミーを吐き出します。賢明です( keyof YourType
は、プロトタイプチェーンのさらに下流で定義されているすべてのパブリック関数を喜んで許可するため)。
Typescriptはおそらくあなたたちにとって優先事項ではないと思いますが、JSでも、 myObject.callMe()
が完全にうまく実行されるのは直感に反しているようですが、その場合はsinon.stub(myObject, "callMe")
は実行されません。 その特定のオブジェクトがどのようにまとめられたかを調べて、スタブする方法を知っている必要はありません。
クラスがJSでよりネイティブなサポートを受けていることを考えると、これは幸せな道を作るための重要なユースケースだと本当に思います。
メソッドがオブジェクトで定義されていないというエラーが表示された場合は、エラーがプロトタイプにある可能性が高いことがわかります。 次に、 myObject.callMe = sinon.stub();
を使用してオブジェクトを直接変更することは、それほど面倒なことではないようです。プロトタイプは変更されていないため、クリーンアップ/ティアダウン関数を作成する手間も省けます。
ええ、回避するのはそれほど難しいことではないと思います。物事がどのように実装されているかを認識するために、私にもっと認知的な負荷をかけているだけです。
また、予想外のように思われるため、同じオブジェクトの2つの連続する行のスタブコードが異なる理由と、分解でスタブの1つを手動で削除した理由を説明するために、テストにコメントを追加する必要があると感じました。しかし、もう1つはサンドボックスによって処理されました。
〜この動作を復元していただきありがとうございます。〜
存在しないプロパティのスタブ化をサポートするユースケースを追加したかった。
私のユースケースでは、構成オブジェクトのプロパティをスタブしています。 configオブジェクトにはさまざまなオプションのキーがあり、開発者のマシンからファイルをロードすることで初期化されます。 特定のテストを実行するとき、これらのキーの1つを既知の値に設定する必要があり、開発者のオブジェクトを元の状態に復元したいと思います。
sandbox.stub(serverSecrets, 'the_key_i_need_set').value(fakeValue)
は、これを伝えるための非常に明確な方法です。 実行時にキーが設定されているかどうかはわかりませんが、同じ動作が得られるのは良いことです。
最も参考になるコメント
〜この動作を復元していただきありがとうございます。〜
存在しないプロパティのスタブ化をサポートするユースケースを追加したかった。
私のユースケースでは、構成オブジェクトのプロパティをスタブしています。 configオブジェクトにはさまざまなオプションのキーがあり、開発者のマシンからファイルをロードすることで初期化されます。 特定のテストを実行するとき、これらのキーの1つを既知の値に設定する必要があり、開発者のオブジェクトを元の状態に復元したいと思います。
sandbox.stub(serverSecrets, 'the_key_i_need_set').value(fakeValue)
は、これを伝えるための非常に明確な方法です。 実行時にキーが設定されているかどうかはわかりませんが、同じ動作が得られるのは良いことです。