【问题标题】:How to mock httpcontext in service如何在服务中模拟 httpcontext
【发布时间】:2014-04-24 19:09:42
【问题描述】:

如何模拟这个服务中的httpcontext?

当我尝试对该服务进行单元测试时,它抱怨 httpcontext 为空。

什么可以用来代替httpcontext?我使用的是网络表单而不是 mvc。我看过多篇关于伪造 httpcontext 类但不使用 webforms 的帖子。

public class FileService : IFileService
{
    public string GetEmployeePicLocation(Employee employee)
    {
        string AgentFilesDirectory = "~\\AgentFiles\\";
        Image newImage = new Image();
        DirectoryInfo diSubPath = 
        new DirectoryInfo(HttpContext.Current.Server
                      .MapPath(AgentFilesDirectory + employee.User_Name));
        string localDIR = AgentFilesDirectory + employee.User_Name + "\\";
        string defaultDIR = AgentFilesDirectory + "nopic\\nopic.jpg";
        string strFile;
        if (diSubPath.Exists)
        {
            FileInfo[] arrJPG = diSubPath.GetFiles("*.jpg");
            FileInfo[] arrPNG = diSubPath.GetFiles("*.png");
            if (!(arrJPG.Length == 0) || !(arrPNG.Length == 0))
            {
                foreach (FileInfo f in diSubPath.GetFiles("*.jpg"))
                {
                    newImage.ImageUrl = localDIR + employee.PicFile;
                }
                foreach (FileInfo f in diSubPath.GetFiles("*.png"))
                {
                    newImage.ImageUrl = localDIR + employee.PicFile;
                }
            }

            else
            {
                newImage.ImageUrl = defaultDIR;
            }


        }
        if (!(diSubPath.Exists))
        {
            newImage.ImageUrl = defaultDIR;
        }

        return newImage.ImageUrl.ToString();
    }
}

【问题讨论】:

    标签: unit-testing integration-testing moq service-layer


    【解决方案1】:

    即使您没有使用 MVC,HttpContextBase 也已在 System.Web 程序集中定义(或者如果您使用的是 .Net 3.5,则在 System.Web.Abstractions 中),因此您仍然可以使用它。更改您的类以获取 HttpContextBase 的实例,您可以创建一个模拟并根据需要进行设置。

    你的班级应该是这样的:

    public class FileService : IFileService
    {
      private HttpContextBase httpContext;
    
      public FileService(HttpContextBase httpContext) {
        this.httpContext = httpContext;
    }
    

    然后在你的测试中:

    var httpContextMock = new Mock<HttpContextBase>();
    httpContextMock.Setup(x => x.SkipAuthorization).Returns(true);
    
    var fileService = new FileService(httpContextMock.Object);
    

    您还需要使用一些 DI 模式,以便 HttpContextBase 实例在您的构造函数中或通过属性注入传递。

    我认为你必须为调用各种 System.IO 类做类似的事情,除非你真的在文件系统设置上有一个位置并准备好为你的测试做。

    【讨论】:

    • @TheTruthIsInCode 是的,您必须对其进行更改。我假设 FileService 是您自己的代码,对吧?
    【解决方案2】:

    我将使用 IoC 并引入一些接口属性,这些属性将提供对选择 HttpContext 属性的访问。测试时,您只需使用您的实现,它会在测试期间为方法提供所需的值。

    这是一些伪代码:

    public class FileService : IFileService
    {
        // injected property
        public IHttpContext CurrentContex {get;set;}
    
        public string GetEmployeePicLocation(Employee employee)
        {
            string AgentFilesDirectory = "~\\AgentFiles\\";
            Image newImage = new Image();
            DirectoryInfo diSubPath = new DirectoryInfo(CurrentContex.Server.MapPath(AgentFilesDirectory + employee.User_Name));
    
            // ...
        }
    }
    

    PS:我认为您正在寻找 HttpContext 存根。请看这里http://martinfowler.com/articles/mocksArentStubs.html

    【讨论】:

      【解决方案3】:

      我看到你得到了一些关于如何模拟它的答案,只是想我会建议一种替代方法,当它需要努力替换静态访问时可能会更简单;

      如果您将对HttpContext 的访问权移至虚拟方法;

      protected virtual DirectoryInfo GetEmployeeDirInfo(Employee employee)
      {
          return new DirectoryInfo(
              HttpContext.Current.Server.MapPath(AgentFilesDirectory + employee.User_Name));
      }
      

      并用;替换旧行进行访问;

      DirectoryInfo diSubPath = GetEmployeeDirInfo(employee);
      

      ...您可以通过手动“模拟”类突然轻松地替换访问权限;

      internal class FileServiceMock : FileService
      {
          protected override DirectoryInfo GetEmployeeDirInfo(Employee employee)
          {
              return new DirectoryInfo("C:\\Temp");
          }
      }
      

      ...只需在您的测试中测试 FileServiceMock。

      void Testmethod() {
          FileService service = new FileServiceMock();
          ...
      

      【讨论】:

        【解决方案4】:

        或者使用 HostingEnvironment.MapPath 。 .它不需要 httpcontext 。 .避免httpcontext

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-29
          • 2015-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-17
          • 2019-12-01
          相关资源
          最近更新 更多