简体   繁体   English

如何避免 HttpContext.Server.MapPath 用于单元测试目的

[英]How to avoid HttpContext.Server.MapPath for Unit Testing Purposes

I am working in an ASP.net MVC 5 application.我在 ASP.net MVC 5 应用程序中工作。 I would like to Unit Test my controller action which looks like this我想对我的控制器动作进行单元测试,它看起来像这样

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

  return View(vm);
}

All the hard work is done by the SetupSearchViewModel() method, which itself is an orchestrator calling many different other methods, one of which is this所有艰苦的工作都是由SetupSearchViewModel()方法完成的,它本身就是一个调用许多不同其他方法的编排器,其中之一就是

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

I plan on doing many Unit Tests on this particular action, but I'm starting with a very simple Unit Test which checks that the correct type of ActionResult is returned我计划对这个特定的操作进行许多单元测试,但我从一个非常简单的单元测试开始,它检查是否返回了正确类型的 ActionResult

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

The test is failing because of the ExtractJsonFile method.由于ExtractJsonFile方法,测试失败。 It uses HttpContext and that is null .它使用HttpContext并且它是null I am using Rhino Mocks to do the mocking of the various classes.我正在使用 Rhino Mocks 来模拟各种类。

What would be the best way to Unit Test this?对此进行单元测试的最佳方法是什么? Darin in this thread suggest we avoid HttpContext.Current if we want our code Unit Tested.如果我们希望我们的代码单元测试,Darin 在这个线程中建议我们避免HttpContext.Current

By the way I tried mocking the HttpContext and made it not null, but then the Server is null , I can go ahead and mock that too I suppose (I don't know how yet), but is there no better way?顺便说一下,我尝试模拟 HttpContext 并使其不为 null,但是Servernull ,我想我也可以继续模拟它(我还不知道如何),但是没有更好的方法吗? I've no problem doing major refactoring if needed.如果需要,我可以进行重大重构。

HttpContext.Server.MapPath would require an underlying virtual directory provider which would not exist during the unit test. HttpContext.Server.MapPath将需要在单元测试期间不存在的底层虚拟目录提供程序。 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而不是耦合到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.您甚至可以更进一步,将整个ExtractJsonFile(string filename)重构为它自己的服务,以避免与磁盘绑定。

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.该服务现在足够灵活,可以在需要时从其他来源(如 Web 服务)获取文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM