How to avoid HttpContext.Server.MapPath for Unit Testing Purposes

守給你的承諾、 提交于 2019-11-27 16:22:28
Nkosi

HttpContext.Server.MapPath would require an underlying virtual directory provider which would not exist during the unit test. Abstract the path mapping behind a service that you can mock to make the code testable.

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

In the implementation of the concrete service you can make your call to map the path and retrieve the file.

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

you would inject the abstraction into your controller or where needed and used

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;
    }
}

Using your mocking framework of choice you can then mock the provider

[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);
}

and not be coupled to HttpContext

You could even go further and refactor the entire ExtractJsonFile(string filename) into its own service to get around being tied to disk as well.

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

This service is now flexible enough to get the file from other sources like web service if needed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!