以前の私たちは、.NETのコアと共通であるの.NET Frameworkが、MVCプロジェクトでは、より多くの特別なクラスのコントローラ、普通とコントローラファーストクラスのリターン結果があるかどうか、ユニットテストの方法と技術の多くの話しましたクラスは通常のクラスのリターンはのActionResultのタイプによって決定されて好きではない返品・コアMVC MVCプロジェクトのリターンIActionResultは非常にカプセル化されたオブジェクトで、私はテストではありませんが、非常に慎重になりたいです非常に簡単なことができません。別のクラスに書き込まれたコードのコードのビジネス・ロジック・ユニットを書くとき、それは可能な限りお勧めしますのでされ、コントローラは、リターンだけシンプルなフロントエンドのテストと、各HTTPリクエストのパラメータおよびステータスデータで。もう一つのポイントは、そのコントローラがありますhttpリクエストが動的に作成到着後、ユニットテスト、などのHttpContext、にModelState、要求、応答、routedata、URI、MetadataProviderなど多くのオブジェクトは、すべての非存在であり、我々はまだそこに大きな差httpリクエスト環境ですが、ときコントローラユニットの結果は、我々が望むものであることを保証するために多くの作業を行うことを通じてテスト。
正しいビューとビューモデルを返すことを確実にするためのアクション
私たちは、わずかにコードを変更し、Indexメソッド内にHomeControllerを使用します
public IActionResult Index()
{
return View("Index","hello");
}
次のようにコードをテスト
[Fact]
public void ViewTest()
{
HomeController hc = new HomeController();
var result = (ViewResult)hc.Index();
var viewName = result.ViewName;
var model = (string)result.Model;
Assert.True(viewName == "Index" && model == "hello");
}
まず、我々はこの方法を必要とするビジネスは、事前に予測可能であるビューを返しますので、私たちがするViewResultに結果をhc.Indexので、変換が失敗した場合、プログラムにバグがあり、コントローラクラスを作成します。
以下は、それぞれ、我々はビュー名がインデックスで主張し、ビューにデータモデルの名前を取得し、値のモデルは、我々はまた、実際のビジネスでモデルしたいと思います、もちろん、上記のコードは明らかに通じ比較的簡単です、こんにちはではより複雑ですアサーション。
ビューのアクションリターンが名前を持っていない、注意すべきであり、この方法は、対応するビューを返す場合は、上記のアサーションが失敗するように、デフォルトの名前は、省略することができるので、あなたは、時間の名前を書いていない場合、我々は主張することができますビュー名は、プロセスは、デフォルトのビューを返し、空です。
アクション正しいViewDataをを確保するために返します
私たちは、次のように、わずかに次の変更IndexメソッドににHomeController:
public IActionResult Index()
{
ViewBag.name = "sto";
return View("Index","hello");
}
次のように試験方法であります
HomeController hc = new HomeController();
var name= result.ViewData["name"];
Assert.True(name=="sto");
疑問を持っていることが、私の同僚のいくつかの上を参照してくださいViewBagはViewDataを設定されており、それを得ることができる理由、インターネットからそれらの多くは、一部の人々は、ダイナミック型の両方であると言う見ていた、辞書型であり、これが唯一の彼らの外部にあります性能は、実際には、唯一の同じオブジェクトを実行している人たちなので、その値はViewDataを[XXX]の方法を通じて取得することができます。
正しい手順は、枝を入力することを確認してください
私たちは、多くの場合、次のコードを参照してください
public IActionResult Index(Student stud)
{
if (!ModelState.IsValid) return BadRequest();
return View("Index","hello");
}
Student
私たちは、次のように読み、コメントを追加したいと
public class Student
{
public string Name { get; set; }
[Range(3,10,ErrorMessage ="年龄必须在三到十岁之间")]
public int Age { get; set; }
public byte Gender { get; set; }
public string School { get; set; }
}
私たちは、年齢にコメント、アイデンティティそれは3-10の間の値でなければなりません。
私たちは、エラー時にリターンがある場合、モデルが結合どうかをテストするには、次のテストを書くBadRequest
[Fact]
public async Task ViewTest()
{
HomeController hc = new HomeController();
var result = hc.Index(new Student{Age=1});
Assert.IsType<BadRequestResult>(result);
}
我々は、上記スタッド年齢が1に設定され、それは3と10との間ではなく、従ってBadRequest A(実際型オブジェクトBadRequestResult)プログラムロジックを返すべき試験しかし、試験は、上記試験は、単一のステップを通過しなかった実行していることがわかります私たちは、デバッグが。なぜ、それをリターンするViewResultオブジェクトで実際にあることがわかった?エラーが発生した場合に結合モデルの検証モデルは、それが書面でオブジェクトをにModelStateする時期Modelstate.IsValidしかし、あるので、それは、実際には非常に簡単です、コントロールを動的に作成されていない、データ・モデルは、動的バインディングではなく、エラーメッセージがアクションでにModelStateに追加されないので、それは真のユニットテストを返すために開始され、それはそれをテストする方法はないではありません、実際にはない、なぜならモデルが結合するときにModelStateプログラムだけでなく動的に追加することができ、我々はまた、コントローラに応じて、独自のビジネス・ロジックを追加することができます。
私たちは、次のように読み取るためのコードを入れて
[Fact]
public async Task ViewTest()
{
HomeController hc = new HomeController();
hc.ModelState.AddModelError("Age", "年龄不在3到10范围内");
var result = hc.Index(new Student{Age=1});
Assert.IsType<BadRequestResult>(result);
}
我々はここで年齢値が違法であることを知っているので、明示的に明示的にコントローラのにModelStateオブジェクトにエラーに書き込まれ、そのようModel.IsvalidはFalseを返す必要がありますので、ロジックは、上記のテストに年BadRequest必要があります。
プログラムは正しいアクションにリダイレクトされていることを確認してください
次のように読むために私たちIndexメソッド
public IActionResult Index(int? id)
{
if (!id.HasValue) return RedirectToAction("Contact","Home");
return View("Index","hello");
}
idがnullで、彼らはRedirectToActionResultが返されます場合は、ホームの連絡先コントローラで次の方法につながります。
[Fact]
public async Task ViewTest()
{
HomeController hc = new HomeController();
var result = hc.Index(null);
var redirect = (RedirectToActionResult) result;
var controllerName = redirect.ControllerName;
var actionName = redirect.ActionName;
Assert.True(controllerName == "Home" && actionName == "Contact");
}
多くの場合、引数が2つの文字列を渡されRediRectToActionは、特別な複雑な計算を必要としないので、もちろん、上記のコードは、非常に意味がありませんredirect.ControllerName
、redirect.ActionName
上記のアクションの名前も本当のコントローラではない得るが、したがって、それらの値を割り当てるための方法は、常に同じです。
我々は、次の変換によってテストより有意義なものにすることができます
[Fact]
public async Task ViewTest()
{
HomeController hc = new HomeController();
var result = hc.Index(null);
var redirect = (RedirectToActionResult) result;
var controllerName = redirect.ControllerName;
var actionName = redirect.ActionName;
Assert.True(
controllerName.Equals(nameof(HomeController).GetControllerName(),
StringComparison.InvariantCultureIgnoreCase) && actionName.Equals(nameof(HomeController.Contact),
StringComparison.InvariantCultureIgnoreCase));
}
我々が使用する上記のコードがNameOf型やメソッドの名前を取得し、手動裁判官を書き、がNameOfにより取得が同じではありませんので、我々は手書きする場合にエラーが発見されますが、問題があるが、我々ががNameOfのにHomeControllerを介して取得するということです名前は文字列であるHomeController
代わりに、ホームの、あまりにも他の種類は、これは、彼らがコントローラーを終了しているので、限り、我々はそれについてあったように、処理し、それに対処することは非常に簡単です。私たちは、文字列クラスの拡張であるはgetControllerName方法を、見て方法
public static class ControllerNameExtension
{
public static string GetControllerName(this string str)
{
if (string.IsNullOrWhiteSpace(str) || !str.EndsWith("Controller",StringComparison.InvariantCultureIgnoreCase))
{
throw new InvalidOperationException("无法获取指定类型的ControllerName");
}
string controllerName =
str.Replace("Controller", string.Empty, StringComparison.InvariantCultureIgnoreCase);
return controllerName;
}
}
この方法は、非常に簡単ですコントローラクラスのコントローラの削除文字列の結果であります
ControllerFactoryので、コントローラを作成する際には大文字と小文字を区別しませんので、我々はすべて対等プラスアプローチを主導し、大文字と小文字を区別しないオプションは、特に長いようであり、私たちは、単純なパッケージを確認する必要があります。
public static class StringComparisionIgnoreCaseExtension
{
public static bool EqualsIgnoreCase(this string str, string other)
{
return str.Equals(other, StringComparison.InvariantCultureIgnoreCase);
}
}
上記の方法は、比較するとき、それがプラスで、非常に簡単ですStringComparison.InvariantCultureIgnoreCase
アサートアサーションは、以下のように、最終的なコードは次のようになります。
Assert.True(
controllerName.EqualsIgnoreCase(nameof(HomeController).GetControllerName()) && actionName.EqualsIgnoreCase(nameof(HomeController.Contact)));
だから、私たちが間違っている場合は、手書きスペルミスの名前または複数のスペースを容易に識別することができるので、メソッドの名前がここに取り除くためにと、コンパイラエラーは、私たちは、エラーを見つけるのに役立ちます。
确保程序重定向到正确路由
時には我々は、指定されたルートにリダイレクトテストする方法を見てみましょう
public IActionResult Index(int? id)
{
if (!id.HasValue) return RedirectToRoute(new{controller="Home",action="Contact"});
return View("Index","hello");
}
上記の方法は、ルート、ここで、このような匿名のオブジェクトを作成する方法について簡単に、なぜオブジェクトのコントローラとして名前、むしろコントローラ名とactionNameのよりアクションにリダイレクトするnullのIDである場合は?MVC我々はどこRouteDataを参照するには、プログラムを実行することができます理解するキーと値のペアの名前は何ですか。
次のように試験方法であります
[Fact]
public async Task ViewTest()
{
HomeController hc = new HomeController();
var result = hc.Index(null);
var redirect = (RedirectToRouteResult) result;
var data = redirect.RouteValues;
var controllerName = data?["controller"]?.ToString();
var actionName = data?["action"]?.ToString();
Assert.True(!string.IsNullOrWhiteSpace(controllerName));
Assert.True(!string.IsNullOrWhiteSpace(actionName));
Assert.True(controllerName.EqualsIgnoreCase(nameof(HomeController).GetControllerName()));
Assert.True(actionName.EqualsIgnoreCase(nameof(HomeController.Contact)));
}
実際に、上記方法及び上記試験RedirectToAction性質が正しいコントローラとアクションを決定するために同様のガイドであり、違いは、取得方法の値ということです。
RedirectToActionとRedirecttoRoute経路は、もはや本明細書の教示を拡張していないサンプルのインデックスキーを取得するための値以上の値を渡すことができます。
適切な指定された短いURLにリダイレクトことを確認します
新しい.NETでコアLocalRedirect
(および恒久的な方法を保つリダイレクトするために永久的な書き換えに対応し、これらをリダイレクトする他の同様の方法はまた、家族を持っている)。それはRedirecttoRouteに似て、ただパラメータがRouteDataではなく、 (理由はデフォルトと内部リダイレクトのみ、ホスト名とIPなし)による短絡です。
次のように私たちにHomeControllerのインデックス方法を読みます:
public IActionResult Index(int? id)
{
if (!id.HasValue) return LocalRedirect("/Home/Hello");
return View("Index","hello");
}
Idはヌルにリダイレクトされた場合は/home/Hello
、バックエンドにきっと私たちは、このように多くのコードを書いたときに、ページ要求、詳細に説明はもはやありません。
次のように試験方法は次のとおりです。
[Fact]
public async Task ViewTest()
{
HomeController hc = new HomeController();
var result = hc.Index(null);
var redirect = (LocalRedirectResult) result;
var url = redirect.Url.Split("/").Where(a=>!string.IsNullOrEmpty(a));
}
これは主に、このアドレスにURLから取得し、その後、いくつかの部分に分割される。最初の部分は第二の部分はアクション名で、デフォルトのコントローラ名です。コードは、もはや書き込みされる背景には、あなたは自分でそれを試していません。
これは、上記の例のすべてがデフォルトルートのみを扱うことに留意すべきである、とルートがデフォルトでない場合など、ルーティングパラメータ、カスタムルーティング、およびAERAルーティング、対処していない、上記の最初の部分は、必ずしも名前をコントローラではありません、また、実際のビジネスに対処する必要性があります。
ビューのテスト
テストMVCコントローラへの追加的な知識とみなさ知識に。この祭りは、MVCのビューに統合テストについて説明し始めました。
理解することの一つは、HTTPリクエストを送信することにより、統合テストは、コントローラオブジェクトのプログラムに入ることができないことを、我々はページの統合テストをのみ見ることができます。
テストページには、テストの主要なテストが含まれており、ページコンテンツのステータスを返します。メインのテストユニットテストの前に、正しい応答が生成され、正しいページに返されていることを確認してくださいビューの名前を返すことで、これを到達するか否かの、正確ですページには、我々は、現在のページの特性に応じて、現在のページの同一性を決定します。統合テスト。このページが持っているがユニークでないかもしれないが、それは別のページやその他の機能を区別することができます。
我々はまだ説明するためにHomeController下ケースとインデックスを使用しています。Indexメソッドは、工場出荷時の設定を変更するために、次のように
public IActionResult Index()
{
return View();
}
ここでの最初のページには、マップが含まれているカルーセルに戻るために、我々は、返されたページが含まれていることを主張することができcarousel
、次のようなキーワード、テストコードを
[Fact]
public async Task ViewIntegrityTest()
{
var response = await _client.GetAsync("/Home/Index");
response.EnsureSuccessStatusCode();
var responseStr = await response.Content.ReadAsStringAsync();
Assert.Contains("carousel", responseStr);
}
上記試験は、中に含まれる(すなわち、全体のビューページである)コンテンツを返さcarousel
このメッセージ。
このページには、実際のプロジェクトのCOSCOの上区別できないことに注意してくださいホームページです、あなたが必要になる場合があり、追加の裁判官は、特定のIDの内容ならば、実際の状況に応じて、適宜、検討する必要があり、名前などになるだろう判決との統合になることがありテストは、メンテナンスの問題をもたらす。時々、あまりにも大きな変化が大きな誤差ユニット・テストにつながる、あまりにも多くのページ、ユニットテストは、直接タイト重いタスクであきらめ、したがって範囲よりも小さくすることができる、より細かいの内容を決定しますより良いが、このページは不変見つけようと、他のものを区別ページすることができます。偶数ページを正しく判断することができる少なくともどこ、区別ではない、これはブラウザを手動ライン上のページの割合かどうかを検出開きます。代わりに、404ページを返さ通常、より信頼性を開きます。
まだもう一つ注意すべきは、物語の終わりまでにない統合テストは、我々はまだ、オンラインのプロジェクトにサンプリング用のページを持っているページのレイアウトが正常で見るということです。もちろん、これらはまた、完了するために、自動化されますが、サンプリングは依然として必要であることができ、しないでくださいすべてのメソッドはシームレスです。