1

我有一个 MVC 控制器,它加载资源文件并用于Server.MapPath获取文件的路径。我想使用Microsoft Fakes框架模拟控制器对象中的Server属性(我知道如何使用其他框架来做到这一点)。

这是代码:

    [HttpGet]
    public ActionResult GeneratePdf(string reportId)
    {
        var template = LoadTemplate(reportId);
        var document = pdfWriter.Write(GetReportModel(reportId), template);
        return File(document, MediaTypeNames.Application.Pdf);
    }

    private byte[] LoadTemplate(string reportId)
    {
        var templatePath = Server.MapPath(string.Format("~/ReportTemplates/{0}.docx", reportId));
        using(var templateContent = System.IO.File.OpenText(templatePath))
        {
            return Encoding.Default.GetBytes(templateContent.ReadToEnd());
        }
    }

我试图模拟的部分是“Server.MapPath”方法。

4

1 回答 1

1

从 Visual Studio 2012 Update 1 开始,您可以使用存根绕过 Controller.Server 属性。

在您的测试项目中使用以下 .Fakes 文件:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true">
  <Assembly Name="System.Web" Version="4.0.0.0"/>
  <StubGeneration>
    <Clear/>
    <Add FullName="System.Web.HttpContextBase!"/>
    <Add FullName="System.Web.HttpServerUtilityBase!"/>
  </StubGeneration>
  <ShimGeneration>
    <Clear/>
  </ShimGeneration>
</Fakes>

您可以像这样编写单元测试:

[TestMethod]
public void TestMethod1()
{
    var target = new TestController();

    var serverStub = new StubHttpServerUtilityBase();
    serverStub.MapPathString = (path) => path.Replace("~", string.Empty).Replace("/", @"\");

    var contextStub = new StubHttpContextBase();
    contextStub.ServerGet = () => serverStub;

    target.ControllerContext = new ControllerContext();
    target.ControllerContext.HttpContext = contextStub;

    var result = (FilePathResult) target.Index();
    Assert.AreEqual(@"\Content\Test.txt", result.FileName);
}

在即将发布的 Update 2 中,您还可以直接使用 Shims 绕过 Controller.Server 属性。这是使用此方法所需的附加 .Fakes 文件。

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true">
  <Assembly Name="System.Web.Mvc" Version="4.0.0.0"/>
  <StubGeneration>
    <Clear/>
  </StubGeneration>
  <ShimGeneration>
    <Clear/>
    <Add FullName="System.Web.Mvc.Controller!"/>
  </ShimGeneration>
</Fakes>

这是测试:

[TestMethod]
public void TestMethod2()
{
    using (ShimsContext.Create())
    {
        var target = new TestController();

        var serverStub = new StubHttpServerUtilityBase();
        serverStub.MapPathString = (path) => path.Replace("~", string.Empty).Replace("/", @"\");

        var controllerShim = new ShimController(target);
        controllerShim.ServerGet = () => serverStub;

        var result = (FilePathResult)target.Index();
        Assert.AreEqual(@"\Content\Test.txt", result.FileName);
    }
}

请注意,此方法在当前版本(更新 1)中不起作用,因为 Fakes 运行时与程序集相关的限制,例如允许部分受信任的调用方的 System.Web.Mvc。如果您今天尝试运行第二个测试,您将收到 VerificationException。

于 2012-12-01T00:42:30.467 回答