.NET MVCコントローラのユニットテストはどのように行うべきですか?
質問
.NET mvcコントローラの効果的なユニットテストに関するアドバイスを探しています。
私が働いているところでは、多くのそのようなテストはデータ層をモックし、特定のデータ層のメソッドが呼び出されることを主張するためにmoqを使用します。これは、本質的に API をテストするのではなく、実装が変更されていないことを検証するので、私には有用であるとは思えません。
私は、返されたビューモデルのタイプが正しいかどうかをチェックするようなことを推奨する記事も読みました。それが何らかの価値を提供することはわかりますが、それだけでは、モッキング コードの多くの行を書く努力に見合うとは思えません (私たちのアプリケーションのデータ モデルは非常に大きく、複雑です)。
どなたか、コントローラユニットテストへのより良いアプローチを提案していただけないでしょうか、あるいは、なぜ上記のアプローチが有効/有用であるのかを説明していただけないでしょうか?
ありがとうございます。
どのように解決するのですか?
コントローラのユニットテストは、データレイヤーではなく、アクションメソッドのコードアルゴリズムをテストする必要があります。これが、データサービスをモックする理由の一つです。コントローラは、リポジトリ/サービス/などから特定の値を受け取り、それらから異なる情報を受け取ったときに異なる動作をすることを期待します。
あなたは、非常に特定のシナリオ/状況において、コントローラが非常に特定の方法で動作することを保証するためにユニットテストを書きます。データレイヤーは、コントローラやアクションメソッドにこれらの状況を提供するアプリの1つの部分です。サービスメソッドがコントローラによって呼び出されたことを保証することは、コントローラが別の場所から情報を取得することを確実にすることができるため、価値があります。
返されるビューモデルのタイプをチェックすることは、間違ったタイプのビューモデルが返された場合、MVCが実行時例外を投げるので、価値があります。ユニットテストを実行することで、実運用でこれが起こるのを防ぐことができます。もしテストが失敗したら、ビューは実運用で例外を投げるかもしれません。
ユニットテストは、リファクタリングをより簡単にするため、価値があります。実装を変更しても、すべてのユニットテストがパスすることを確認することで、動作が同じであることを保証することができます。
コメント1への回答
もしテスト中のメソッドの実装を変更することで、下位層のモックされたメソッドを変更/削除する必要がある場合、ユニットテストも変更しなければなりません。しかし、これはあなたが考えるほど頻繁には起こらないはずです。
典型的なレッド・グリーン・リファクタリングのワークフローは、ユニットテストを書くために次のように呼びかけます。 の前に を書くことです。(これは、短い時間の間、テストコードがコンパイルされないことを意味し、多くの若い/経験の浅い開発者がレッド・グリーン・リファクタリングを採用するのが難しい理由です)。
もしあなたが最初にユニットテストを書くなら、コントローラが下位の層から情報を取得する必要があることを知っている地点に来るでしょう。その情報を取得しようとすることを確認するにはどうしたらよいでしょうか。情報を提供する下位層のメソッドをモック化し、下位層のメソッドがコントローラによって呼び出されることを保証することです。
モックされたメソッドを変更または削除するために、コントローラのアクションメソッドと対応するユニットテストを変更しなければならないとき、あなたは本当にコントローラの動作を変更していることになります。リファクタリングとは、定義上、全体の動作や期待される結果を変えることなく、実装を変更することを意味します。
レッド-グリーン-リファクタリングは、バグやコードの欠陥が現れる前にそれを防ぐのに役立つ品質保証のアプローチです。一般的に、開発者はバグが発生した後にバグを取り除くために実装を変更します。ですから、繰り返しになりますが、あなたが心配しているようなケースは、あなたが考えているほど頻繁に起こるものではありません。
関連
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み] 'SubSonic.Schema .DatabaseColumn' 型のオブジェクトをシリアライズする際に、循環参照が検出されました。
-
[解決済み】ファイルへの読み書きの際に共有違反のIOExceptionが発生する C#
-
[解決済み] プライベートメソッド、フィールド、インナークラスを持つクラスをテストするにはどうすればよいですか?
-
[解決済み] Pythonの関数が例外を投げるかどうかをテストするにはどうすればよいですか?
-
[解決済み] フェイク、モッキング、スタビングの違いとは?
-
[解決済み] TDDのためのJavaScriptユニットテストツール
-
[解決済み] Gradleを使用して1つのユニットテストクラスのみを実行する方法
-
[解決済み] データベース駆動型アプリケーションのユニットテストに最適な戦略とは?
-
[解決済み] Entity Framework 6のユニットテストはどうなっているのか、気になりますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】"出力タイプがクラスライブラリのプロジェクトは直接起動できない"
-
[解決済み] 保護レベルによりアクセス不能になりました。
-
[解決済み】"The ConnectionString property has not been initialized "を修正する方法
-
[解決済み】プロジェクトビルド時のエラー。エディタでスクリプトにコンパイルエラーがあるため、Playerのビルドにエラーが発生する
-
[解決済み】パラメータ付きRedirectToAction
-
[解決済み】IntPtrとは一体何なのか?
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。
-
[解決済み】ユーザー設定値を別のユーザー設定値で設定する