如何在服务中模拟httpcontext

时间:2014-04-24 19:09:43

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

如何模拟此服务中的httpcontext?

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

可以用什么代替httpcontext?我使用的是webforms而不是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();
    }
}

4 个答案:

答案 0 :(得分:2)

即使你没有做MVC,在System.Web程序集中定义了HttpContextBase(或者如果你在System.Web.Abstractions中使用.Net 3.5),那么你仍然可以使用它。更改您的类以获取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类。

答案 1 :(得分:0)

我会使用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

答案 2 :(得分:0)

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

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

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

并替换使用;

进行访问的旧行
DirectoryInfo diSubPath = GetEmployeeDirInfo(employee);

...你可以通过&#34; mocking&#34;突然轻而易举地取代访问权限。该手动;

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

...并在测试中测试FileServiceMock。

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

答案 3 :(得分:0)

或者使用HostingEnvironment.MapPath。 .it不需要httpcontext。 .avoid httpcontext