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

查看:70
本文介绍了如何避免出于单元测试目的的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.

对此进行单元测试的最佳方法是什么?达林在此线程中建议,如果我们希望我们避免使用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并将其设置为非null的方式,但是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天全站免登陆