如何避免 HttpContext.Server.MapPath 用于单元测试目的 [英] How to avoid HttpContext.Server.MapPath for Unit Testing Purposes

查看:16
本文介绍了如何避免 HttpContext.Server.MapPath 用于单元测试目的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 ASP.net MVC 5 应用程序中工作.我想对我的控制器动作进行单元测试,它看起来像这样

I am working in an ASP.net MVC 5 application. I would like to Unit Test my controller action which looks like this

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

  return View(vm);
}

所有艰苦的工作都由 SetupSearchViewModel() 方法完成,该方法本身就是一个调用许多其他方法的编排器,其中一个是这个

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

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

我计划对这个特定操作进行许多单元测试,但我从一个非常简单的单元测试开始,它检查是否返回了正确类型的 ActionResult

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

[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 Mocks 来模拟各种类.

The test is failing because of the ExtractJsonFile method. It uses HttpContext and that is null. I am using Rhino Mocks to do the mocking of the various classes.

单元测试的最佳方法是什么?此线程中的 Darin 建议我们避免使用 HttpContext.Current 如果我们希望我们的代码进行单元测试.

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.

顺便说一下,我尝试模拟 HttpContext 并使其不为空,但是 Servernull,我想我也可以继续模拟它(我还不知道如何),但没有更好的方法吗?如果需要,我可以进行重大重构.

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? I've no problem doing major refactoring if needed.

推荐答案

HttpContext.Server.MapPath 需要一个在单元测试期间不存在的底层虚拟目录提供程序.抽象服务背后的路径映射,您可以模拟该服务以使代码可测试.

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

而不是耦合到HttpContext

您甚至可以更进一步,将整个 ExtractJsonFile(string filename) 重构为它自己的服务,以避免与磁盘绑定.

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

此服务现在足够灵活,可以在需要时从其他来源(如 Web 服务)获取文件.

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

这篇关于如何避免 HttpContext.Server.MapPath 用于单元测试目的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆