代码之家  ›  专栏  ›  技术社区  ›  James Lawruk

将HttpResponse对象作为参数的方法的单元测试。OutputStream不可用

  •  8
  • James Lawruk  · 技术社区  · 15 年前

    我正在尝试为一个将HttpResponse对象作为参数的方法创建一个单元测试。正确的做法是什么?我希望你们这些经验丰富的单元测试人员能帮助我。

    其他信息: 我试图通过传入StringWriter来创建一个假的HttpResponse对象。

    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    HttpResponse response = new HttpResponse(sw);
    RssGenerator.Generate(response, otherParameters);
    

    测试失败,并显示以下消息: System.Web.HttpException:使用自定义TextWriter时,OutputStream不可用。 正在测试的方法是类库dll的一部分。它使用响应对象的OutputStream创建带有XMLWriter的RSSFeed。

    6 回复  |  直到 9 年前
        1
  •  13
  •   Frank Schwieterman    15 年前

    特别是,使用HttpResponseBase( http://msdn.microsoft.com/en-us/library/system.web.httpresponsebase.aspx )作为输入参数,而不是HttpResponse。然后可以从测试中模拟HttpResponseBase。当您要传入一个真正的HttpResponse时,使用HttpResponseWrapper生成一个HttpResponseBase。

        2
  •  3
  •   Community CDub    8 年前

    要成为真正的单元,您应该模拟HttpResponse和其他一切,只测试您的方法代码。我不知道有什么C#mock实用程序,但是 question might help

    然后您可以执行类似的操作(示例是带有Mockito的Java):

    HttpResponse response = mock(HttpResponse.class);
    OutputStream outputStream = mock(OutputStream.class);
    when(response.getOutputStream()).thenReturn(outputStream); 
    
    RssGenerator.generate(response, otherParameters);
    

        3
  •  2
  •   Ricardo stands with Ukraine    9 年前

    _mockResponse = new Mock<HttpResponseBase>();
    _contentType = string.Empty;
    _mockResponse.SetupSet(r => r.ContentType = It.IsAny<string>()).Callback<string>(value => _contentType = value);
    _header = new KeyValuePair<string, string>();
    _mockResponse.Setup(r => r.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback((string name, string value) => _header = new KeyValuePair<string, string>(name, value));
    _writer = new StringBuilder();
    _mockResponse.Setup(r => r.Write(It.IsAny<string>())).Callback<string>(s => _writer.Append(s));
    var data = "This is the string to send as response";
    
    UTIL.SendStringAsHttpResponse(data, _mockResponse.Object);
    
    Assert.That(_contentType, Is.EqualTo("application/CSV"));
    Assert.That(_header.Value, Is.EqualTo("attachment; filename=download.csv"));
    Assert.That(_writer.ToString(), Is.EqualTo(data));
    

    其中,SendStringAsHttpResponse定义为

    public static void SendStringAsHttpResponse(string data, HttpResponseBase response)
    
        4
  •  1
  •   Guffa    15 年前

    的构造函数 HttpResponse 不是供您使用的,它只供ASP.NET页面循环使用,因此没有关于如何创建的文档。

    你必须设置 HttpResponse 对象,以便它使用 HttpWriter ,否则它将不允许您访问底层流。但是,构造函数设置了 _httpWriter 可变到 null ,因此您必须找到其他方法来设置它。

    你可以使用 .NET Reflector 要在中挖掘的程序 HttpResponse

        5
  •  1
  •   ryber    15 年前

    因此,模拟HttpResponse的问题在于它是密封的,因此您无法扩展它(大多数模拟具体类的模拟框架只是覆盖虚拟方法)。微软也很好心,没有为其中的大多数提供接口…所以,谢谢微软。

        6
  •  0
  •   Rodney Gitzel    15 年前

    只是

    您无法创建现有实现的自己的实例的原因是,它将与您的应用程序服务器紧密关联,并且可能需要各种其他的gunk来实例化。

    如果结果证明我需要比简单的HttpResponse空版本更复杂的东西,那么我会考虑不直接测试这个方法:也许一个或两个级别的测试会更简单,并且会为我提供相同级别的代码信心。