2016-07-19 4 views
2

ASP.net MVC 5 응용 프로그램에서 작업하고 있습니다. 내가 단위 시험이단위 테스트 목적으로 HttpContext.Server.MapPath를 피하는 방법

public ActionResult Search() 
{ 
    var vm = SetupSearchViewModel(); 

    return View(vm); 
} 

모든 노력 자체가이

중 하나는 여러 가지 다른 방법을 호출 지휘자, 인 SetupSearchViewModel() 방법에 의해 이루어집니다처럼 보이는 내 컨트롤러 액션을 싶습니다
private string ExtractJsonFile(string filename) 
{ 
    var filePath = HttpContext.Server.MapPath(filename); 
    var json = System.IO.File.ReadAllText(filePath); 
    return json; 
} 

나는이 특정 작업에 많은 단위 테스트를 할 계획,하지만 난 ActionResult의 올바른 유형이 반환되는 것을 확인하는 아주 간단한 단위 테스트와 함께 시작 해요

[Test] 
public void Search_Get_ReturnsViewResult() 
{ 
    // arrange 
    var performanceController = PerformanceControllerInstance; 
    // act 
    var result = performanceController.Search(); 
    //assert 
    Assert.IsNotNull(result as ViewResult); 
} 

ExtractJsonFile 메서드 때문에 테스트에 실패했습니다. 그것은 HttpContext을 사용하며 그 값은 null입니다. Rhino Mock을 사용하여 다양한 클래스를 조롱합니다.

단위 테스트에 가장 적합한 방법은 무엇입니까? Darin in this thread 우리가 코드 테스트를 원한다면 HttpContext.Current을 피할 것을 제안합니다. 내가 시도하는 방식 조롱으로

HttpContext를하고 null이 아닌 만들었지 만, 다음 Servernull, 나는 앞서 갈 수도 내가 (나는 방법을 아직 모른다) 가정 것을 모의하지만, 더 좋은가 방법? 필요한 경우 주요 리팩터링을 수행하는 데 아무런 문제가 없습니다.

답변

4

HttpContext.Server.MapPath 단위 테스트 중에 존재하지 않는 기본 가상 디렉터리 공급자가 필요합니다. 코드를 테스트 할 수 있도록 조롱 할 수있는 서비스 뒤에있는 경로 매핑을 추상화합니다.

public interface IPathProvider { 
    string MapPath(string path); 
} 

구체적인 서비스를 구현할 때 경로를 매핑하고 파일을 검색하도록 호출 할 수 있습니다.

public class ServerPathProvider: IPathProvider { 
    public string MapPath(string path) { 
     return HttpContext.Current.Server.MapPath(path); 
    } 
} 

당신은 당신이 다음

[Test] 
public void Search_Get_ReturnsViewResult() { 
    // arrange 
    IPathProvider mockedPathProvider = //...insert your mock/fake/stub here 
    var performanceController = PerformanceControllerInstance(mockedPathProvider); 
    // act 
    var result = performanceController.Search(); 
    //assert 
    Assert.IsNotNull(result as ViewResult); 
} 

하지가 결합 될 바이더를 조롱 할 수 있습니다 컨트롤러에 추상화를 주입 또는 어디에 필요하고 선택의 조롱 프레임 워크를 사용

public MyController : Controller { 

    public MyController(IPathProvider pathProvider) { 
     this.pathProvider = pathProvider; 
    } 

    //...other code removed for brevity 

    private string ExtractJsonFile(string filename) { 
     var filePath = pathProvider.MapPath(filename); 
     var json = System.IO.File.ReadAllText(filePath); 
     return json; 
    } 
} 

을 사용하는 것 ~ HttpContext

너도 갈 수있어. 그녀와 리팩토링자인 ExtractJsonFile(string filename)은 자체 서비스로 디스크에 묶어 둘 수 있습니다.

public interface IJsonProvider { 
    string ExtractJsonFile(string filename); 
} 

이 서비스는 이제 필요한 경우 웹 서비스와 같은 다른 출처에서 파일을 가져올만큼 충분히 유연합니다.

관련 문제