카테고리 없음

HttpContextBase를 이용해서 ASP.NET 코드의 테스트 가능성 높이기

wafe 2009. 12. 19. 21:03
유닛 테스트를 중요하게 생각하여 설계한 코드라면 HttpContext 같이 ASP.NET 프레임워크에 종속되어 테스트가 불가능해지는 클래스들은 진작에 어댑터 등을 이용하여 분리시켜 두었을 것이다. 하지만 이미 작성된 코드가 많은 상황에서 유닛 테스트를 도입할 때에는 HttpContextBase 클래스가 유용하게 사용될 수 있다.

HttpContextBase 클래스는 ASP.NET MVC에서 쓰이는 클래스라서 (Controller.HttpContext Property 참조) 3.5 SP1부터 쓸 수 있고, System.Web.Abstractions 어셈블리(네임스페이스는 System.Web)를 참조에 추가하면 된다.

HttpContextBase 클래스는 기존의 HttpContext 클래스와 완전히 동일한 멤버들을 노출하고 있고, HttpContext 인스턴스를 쉽게 HttpContextBase 인스턴스로 전환할 수 있도록 HttpContextWrapper 클래스를 같이 제공하고 있다. 포함된 어셈블리도 ASP.NET MVC와는 분리된 어셈블리이다. 따라서 ASP.NET 응용프로그램에서도 기존에 HttpContext 인스턴스를 사용하는 곳에서는 동일하게 HttpContextBase 인스턴스를 사용할 수 있다.

ASP.NET MVC의 목표에 맞게, HttpContextBase의 모든 멤버는 virtual로 선언되어 있어서 HttpContext를 사용하는 코드를 쉽게 유닛 테스트 할 수 있게 된다. (Rhino.Mocks 같은 mock framework을 쓴다면 금상첨화)

비록 HttpContext를 쓰던 곳에 HttpContextBase를 그대로 쓸 수 있다고는 하지만 기존의 ASP.NET 코드 상태에 따라서는 당연히 수정이 필요한 곳이 생긴다.
  • 정적(static)으로 선언된 HttpContex.Current 속성을 직접 사용하는 메서드는 HttpContextBase 인스턴스를 파라미터로 받아서 사용하게 수정해야 한다.
  • 혹은 클래스에 HttpContextBase 형식 필드를 추가해서 그것을 사용하도록 수정해야 한다.
  • new HttpContextWrapper(HttpContext.Current) 같은 형태로 클래스 메서드나 생성자의 파라미터로 넘겨주도록 수정한다.
한 가지 특이하게 수정해야 했던 부분은 Reflection을 사용하는 경우였다. 기존의 코드는 HttpModule 내부에서 HttpContext로부터 HttpWorkerRequest를 얻을 때 Type 클래스를 사용하고 있었다. 

request = (HttpWorkerRequest)type.GetProperty("WorkerRequest", bindingAttr).GetValue(context, null);

다행히 이 경우에는 GetService 메서드를 사용하여 수정할 수 있었고, 이 방법이 정석이라고 생각된다.
request = (HttpWorkerRequest)context.GetService(typeof(HttpWorkerRequest));


이런 식으로 HttpContextBase 클래스를 사용하도록 수정하면, HttpContextBase를 통해서 얻는 Request나 Response 인스턴스에도 동일한 패턴이 적용되어 있으므로 쉽게 테스트 가능한 코드를 얻을 수 있게 된다.