コントローラークラスのテスト
チュートリアル: ASP.NET MVC での TDD の使用
上記リンク先からダウンロードできるサンプルソースはMVC2のときのものですが、十分参考になります。
コントローラークラスに対するテストを勘違いしていたところがあったので、自コメント付けてソースを丸々貼り付け。
コントローラークラスのテストは正直いらないんじゃ?と思ってた(または優先度低い)。単体テストというよりは複合テスト?
また、テストの書き方も参考なりました。
コントローラークラスに対するテストを勘違いしていたところがあったので、自コメント付けてソースを丸々貼り付け。
コントローラークラスのテストは正直いらないんじゃ?と思ってた(または優先度低い)。単体テストというよりは複合テスト?
また、テストの書き方も参考なりました。
- 確認項目ごとにテストメソッドを定義する。
- 同一メソッドに複数の仕様があり、それらを確認する必要があればそのぶんだけ、そのメソッドに対するテストが存在すべきである。
[TestClass] public class HomeControllerTest { //ビュー名のテスト [TestMethod] public void Index_Get_AsksForIndexView() { // Arrange var controller = GetHomeController(new InMemoryContactRepository()); // Act ViewResult result = controller.Index(); // Assert Assert.AreEqual("Index", result.ViewName); } //ビューが持つモデル値のテスト [TestMethod] public void Index_Get_RetrievesAllContactsFromRepository() { // Arrange Contact contact1 = GetContactNamed(1, "Orlando", "Gee"); Contact contact2 = GetContactNamed(2, "Keith", "Harris"); InMemoryContactRepository repository = new InMemoryContactRepository(); repository.Add(contact1); repository.Add(contact2); var controller = GetHomeController(repository); // Act var result = controller.Index(); // Assert var model = (IEnumerable<Contact>)result.ViewData.Model; CollectionAssert.Contains(model.ToList(), contact1); CollectionAssert.Contains(model.ToList(), contact1); } //情報追加するアクションメソッド呼び出し後のContactレコード追加確認 [TestMethod] public void Create_Post_PutsValidContactIntoRepository() { // Arrange InMemoryContactRepository repository = new InMemoryContactRepository(); HomeController controller = GetHomeController(repository); Contact contact = GetContactID_1(); // Act controller.Create(contact); //情報追加するアクションメソッド呼び出し // Assert IEnumerable<Contact> contacts = repository.GetAllContacts(); Assert.IsTrue(contacts.Contains(contact)); } //リダイレクト先の確認 //⇒前のテスト(Create_Post_PutsValidContactIntoRepository)と同じアクションメソッドに対するテストだが、 //確認項目事にテストメソッドを作成している。以降もCreateメソッドに対するテストが続く。 [TestMethod] public void Create_Post_ReturnsRedirectOnSuccess() { // Arrange HomeController controller = GetHomeController(new InMemoryContactRepository()); Contact model = GetContactID_1(); // Act var result = (RedirectToRouteResult)controller.Create(model); // Assert Assert.AreEqual("Index", result.RouteValues["action"]); } //モデル状態がエラーな状態でアクションメソッドを呼び出すテスト //Createアクションメソッドの仕様ではHttpGetなCreateビューが返されるので、それの確認を行っている。 [TestMethod] public void Create_Post_ReturnsViewIfModelStateIsNotValid() { // Arrange HomeController controller = GetHomeController(new InMemoryContactRepository()); // Simply executing a method during a unit test does just that - executes a method, and no more. // The MVC pipeline doesn't run, so binding and validation don't run. controller.ModelState.AddModelError("", "mock error message"); Contact model = GetContactNamed(1, "", ""); // Act var result = (ViewResult)controller.Create(model); // Assert Assert.AreEqual("Create", result.ViewName); } //アクションメソッドで例外を発生させるテスト [TestMethod] public void Create_Post_ReturnsViewIfRepositoryThrowsException() { // Arrange InMemoryContactRepository repository = new InMemoryContactRepository(); Exception exception = new Exception(); repository.ExceptionToThrow = exception; HomeController controller = GetHomeController(repository); Contact model = GetContactID_1(); // Act var result = (ViewResult)controller.Create(model); // Assert Assert.AreEqual("Create", result.ViewName); ModelState modelState = result.ViewData.ModelState[""]; Assert.IsNotNull(modelState); Assert.IsTrue(modelState.Errors.Any()); Assert.AreEqual(exception, modelState.Errors[0].Exception); } // </snippet7> Contact GetContactID_1() { return GetContactNamed(1, "Janet", "Gates"); } Contact GetContactNamed(int id, string fName, string lName) { return new Contact { Id = id, FirstName = fName, LastName = lName, Phone = "710-555-0173", Email = "janet1@adventure-works.com" }; } //コントローラーオブジェクトを生成する。 private static HomeController GetHomeController(IContactRepository repository) { HomeController controller = new HomeController(repository); controller.ControllerContext = new ControllerContext() { Controller = controller, RequestContext = new RequestContext(new MockHttpContext(), new RouteData()) }; return controller; } //モックHttpContextクラス private class MockHttpContext : HttpContextBase { private readonly IPrincipal _user = new GenericPrincipal(new GenericIdentity("someUser"), null /* roles */); public override IPrincipal User { get { return _user; } set { base.User = value; } } } }