10
ユニットテストアプリケーションロジックと不信な言語構成要素の境界線はどこですか?
次のような関数を考えてみましょう。 function savePeople(dataStore, people) { people.forEach(person => dataStore.savePerson(person)); } 次のように使用できます。 myDataStore = new Store('some connection string', 'password'); myPeople = ['Joe', 'Maggie', 'John']; savePeople(myDataStore, myPeople); 独自の単体テストがあるか、ベンダーが提供していると仮定しましょうStore。いずれにせよ、私たちは信頼していStoreます。さらに、エラー処理(たとえば、データベースの切断エラーなど)はの責任ではないと仮定しましょうsavePeople。実際、ストア自体が魔法のようなデータベースであり、何らかのエラーが発生する可能性はないと仮定しましょう。 これらの仮定を考えると、問題は次のとおりです。 savePeople()単体テストする必要がありますか、それとも組み込みのforEach言語構成のテストに相当しますか? もちろん、モックdataStoreを渡し、dataStore.savePerson()各人に1回呼び出されることをアサートすることもできます。このようなテストは実装の変更に対するセキュリティを提供するという議論を確かに行うことができます。たとえば、forEach従来のforループや他の反復方法に置き換えることを決めた場合です。そのため、テストは完全に簡単ではありません。そしてそれでもひどく近いようです... より実りの多い別の例を次に示します。他のオブジェクトや機能を調整する以外の何もしない機能を考えてください。例えば: function bakeCookies(dough, pan, oven) { panWithRawCookies = pan.add(dough); oven.addPan(panWithRawCookies); oven.bakeCookies(); oven.removePan(); } このような機能は、どのようにユニットテストされるべきでしょうか?私は単純にモックていないユニットテストのいずれかの種類を想像するのは難しいdough、panとovenして、メソッドがそれらに呼ばれていると主張します。しかし、そのようなテストは、関数の正確な実装を複製する以上のことはしていません。 意味のあるブラックボックスの方法で関数をテストできないことは、関数自体の設計上の欠陥を示していますか?もしそうなら、どのように改善できますか? bakeCookies例の動機となる質問をさらに明確にするために、より現実的なシナリオを追加します。これは、テストを追加してレガシーコードをリファクタリングしようとしたときに遭遇したシナリオです。 ユーザーが新しいアカウントを作成するとき、いくつかのことを行う必要があります:1)新しいユーザーレコードをデータベースに作成する必要がある2)ウェルカムメールを送信する必要がある3)ユーザーのIPアドレスを詐欺のために記録する必要がある目的。 そこで、すべての「新規ユーザー」ステップを結び付けるメソッドを作成します。 function createNewUser(validatedUserData, emailService, dataStore) …