컨트롤러 작업에 대한 단위 테스트를 만드는 방법을 알아봅니다. 이 자습서에서 Stephen Walther는 컨트롤러 작업이 특정 보기를 반환하는지, 특정 데이터 집합을 반환하는지, 다른 유형의 작업 결과를 반환하는지 테스트하는 방법을 보여 줍니다.
이 자습서의 목표는 ASP.NET MVC 애플리케이션에서 컨트롤러에 대한 단위 테스트를 작성하는 방법을 보여 주는 것입니다. 세 가지 유형의 단위 테스트를 빌드하는 방법에 대해 설명합니다. 컨트롤러 작업에서 반환된 뷰를 테스트하는 방법, 컨트롤러 작업에서 반환된 데이터 보기 작업을 테스트하는 방법 및 컨트롤러 작업 중 하나가 두 번째 컨트롤러 작업으로 리디렉션되는지 여부를 테스트하는 방법을 알아봅니다.
테스트에서 컨트롤러 만들기
먼저 테스트하려는 컨트롤러를 만들어 보겠습니다. 라는 ProductController
컨트롤러는 목록 1에 포함됩니다.
목록 1 – ProductController.cs
using System;
using System.Web.Mvc;
namespace Store.Controllers
{
public class ProductController : Controller
{
public ActionResult Index()
{
// Add action logic here
throw new NotImplementedException();
}
public ActionResult Details(int Id)
{
return View("Details");
}
}
}
에는 ProductController
및 라는 두 개의 작업 메서드가 Index()
포함되어 있습니다 Details()
. 두 작업 메서드 모두 뷰를 반환합니다.
Details()
작업은 ID라는 매개 변수를 수락합니다.
컨트롤러에서 반환된 보기 테스트
가 올바른 보기를 반환하는지 여부를 ProductController
테스트한다고 상상해 보십시오. 작업이 호출될 때 ProductController.Details()
세부 정보 보기가 반환되는지 확인하려고 합니다. 목록 2의 테스트 클래스에는 작업에서 반환된 뷰를 테스트하기 위한 단위 테스트가 포함되어 있습니다 ProductController.Details()
.
목록 2 – ProductControllerTest.cs
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers
{
[TestClass]
public class ProductControllerTest
{
[TestMethod]
public void TestDetailsView()
{
var controller = new ProductController();
var result = controller.Details(2) as ViewResult;
Assert.AreEqual("Details", result.ViewName);
}
}
}
목록 2의 클래스에는 라는 TestDetailsView()
테스트 메서드가 포함됩니다. 이 메서드에는 세 줄의 코드가 포함되어 있습니다. 코드의 첫 번째 줄은 클래스의 ProductController
새 instance 만듭니다. 두 번째 코드 줄은 컨트롤러의 Details()
작업 메서드를 호출합니다. 마지막으로 코드의 마지막 줄은 작업에서 반환된 Details()
뷰가 세부 정보 보기인지 여부를 확인합니다.
속성은 ViewResult.ViewName
컨트롤러에서 반환된 뷰의 이름을 나타냅니다. 이 속성 테스트에 대한 하나의 큰 경고입니다. 컨트롤러가 뷰를 반환할 수 있는 방법에는 두 가지가 있습니다. 컨트롤러는 다음과 같은 보기를 명시적으로 반환할 수 있습니다.
public ActionResult Details(int Id)
{
return View("Details");
}
또는 다음과 같이 컨트롤러 작업의 이름에서 뷰 이름을 유추할 수 있습니다.
public ActionResult Details(int Id)
{
return View();
}
이 컨트롤러 작업은 라는 Details
뷰도 반환합니다. 그러나 뷰의 이름은 작업 이름에서 유추됩니다. 뷰 이름을 테스트하려면 컨트롤러 작업에서 뷰 이름을 명시적으로 반환해야 합니다.
키보드 조합 Ctrl-R, A 를 입력하거나 솔루션에서 모든 테스트 실행 단추를 클릭하여 목록 2 에서 단위 테스트를 실행할 수 있습니다(그림 1 참조). 테스트가 통과하면 그림 2에 테스트 결과 창이 표시됩니다.
그림 01: 솔루션에서 모든 테스트 실행(전체 크기 이미지를 보려면 클릭)
그림 02: 성공! (전체 크기 이미지를 보려면 클릭)
컨트롤러에서 반환된 데이터 보기 테스트
MVC 컨트롤러는 라는 View Data
항목을 사용하여 뷰에 데이터를 전달합니다. 예를 들어 작업을 호출할 때 특정 제품에 대한 세부 정보를 표시하려는 경우를 상상해 보십시오 ProductController Details()
. 이 경우 모델에 정의된 클래스의 Product
instance 만들고 를 활용하여 View Data
instance Details
뷰에 전달할 수 있습니다.
목록 3에서 수정된 ProductController
에는 제품을 반환하는 업데이트 Details()
된 작업이 포함됩니다.
목록 3 – ProductController.cs
using System;
using System.Web.Mvc;
namespace Store.Controllers
{
public class ProductController : Controller
{
public ActionResult Index()
{
// Add action logic here
throw new NotImplementedException();
}
public ActionResult Details(int Id)
{
var product = new Product(Id, "Laptop");
return View("Details", product);
}
}
}
먼저 작업은 Details()
랩톱 컴퓨터를 나타내는 클래스의 Product
새 instance 만듭니다. 다음으로 클래스의 Product
instance 메서드에 두 번째 매개 변수 View()
로 전달됩니다.
단위 테스트를 작성하여 예상 데이터가 뷰 데이터에 포함되어 있는지 여부를 테스트할 수 있습니다. 목록 4의 단위 테스트는 작업 메서드를 호출 ProductController Details()
할 때 랩톱 컴퓨터를 나타내는 제품이 반환되는지 여부를 테스트합니다.
목록 4 – ProductControllerTest.cs
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers
{
[TestClass]
public class ProductControllerTest
{
[TestMethod]
public void TestDetailsViewData()
{
var controller = new ProductController();
var result = controller.Details(2) as ViewResult;
var product = (Product) result.ViewData.Model;
Assert.AreEqual("Laptop", product.Name);
}
}
}
목록 4에서 메서드는 TestDetailsView()
메서드를 호출하여 반환된 데이터 보기를 테스트합니다 Details()
. 는 ViewData
메서드를 호출하여 반환된 의 ViewResult
속성으로 노출됩니다 Details()
. 속성에는 ViewData.Model
보기에 전달된 제품이 포함됩니다. 테스트는 단순히 보기 데이터에 포함된 제품에 Laptop이라는 이름이 포함되어 있음을 확인합니다.
컨트롤러에서 반환된 작업 결과 테스트
더 복잡한 컨트롤러 작업은 컨트롤러 작업에 전달된 매개 변수의 값에 따라 다양한 유형의 작업 결과를 반환할 수 있습니다. 컨트롤러 작업은 , RedirectToRouteResult
또는 JsonResult
를 비롯한 다양한 유형의 작업 결과를 반환할 ViewResult
수 있습니다.
예를 들어 목록 5의 수정된 Details()
작업은 유효한 제품 ID를 작업에 전달할 때 보기를 반환 Details
합니다. 값이 1보다 작은 ID인 잘못된 제품 ID를 전달하면 작업으로 Index()
리디렉션됩니다.
목록 5 – ProductController.cs
using System;
using System.Web.Mvc;
namespace Store.Controllers
{
public class ProductController : Controller
{
public ActionResult Index()
{
// Add action logic here
throw new NotImplementedException();
}
public ActionResult Details(int Id)
{
if (Id < 1)
return RedirectToAction("Index");
var product = new Product(Id, "Laptop");
return View("Details", product);
}
}
}
목록 6에서 Details()
단위 테스트를 통해 작업의 동작을 테스트할 수 있습니다. 목록 6의 단위 테스트는 값이 -1인 ID가 메서드에 Index
전달될 때 보기로 Details()
리디렉션되는지 확인합니다.
목록 6 – ProductControllerTest.cs
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers
{
[TestClass]
public class ProductControllerTest
{
[TestMethod]
public void TestDetailsRedirect()
{
var controller = new ProductController();
var result = (RedirectToRouteResult) controller.Details(-1);
Assert.AreEqual("Index", result.Values["action"]);
}
}
}
컨트롤러 작업에서 메서드를 호출 RedirectToAction()
하면 컨트롤러 작업은 를 반환합니다 RedirectToRouteResult
. 테스트는 가 RedirectToRouteResult
라는 컨트롤러 작업 Index
으로 사용자를 리디렉션할지 여부를 확인합니다.
요약
이 자습서에서는 MVC 컨트롤러 작업에 대한 단위 테스트를 빌드하는 방법을 알아보았습니다. 먼저 컨트롤러 작업에서 올바른 뷰를 반환하는지 확인하는 방법을 알아보았습니다. 사용 하는 방법을 배웠습니다는 ViewResult.ViewName
뷰의 이름을 확인 하는 속성입니다.
다음으로, 의 View Data
내용을 테스트하는 방법을 검토했습니다. 컨트롤러 작업을 호출한 후 올바른 제품이 반환 View Data
되었는지 여부를 검사 방법을 알아보았습니다.
마지막으로 컨트롤러 작업에서 다른 유형의 작업 결과가 반환되는지 여부를 테스트하는 방법을 설명했습니다. 컨트롤러가 를 반환하는지 또는 를 반환 ViewResult
하는지 테스트하는 RedirectToRouteResult
방법을 알아보았습니다.