- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用一个Http模块,该模块仅记录响应时间和大小,然后将结果附加到响应正文中。
我的模块看起来像这样:
public override void PreRequestHandlerExecute(HttpContextBase context)
{
// Add a filter to capture response stream
context.Response.Filter = new ResponseSniffer(context.Response.Filter);
}
public override void ApplicationEndRequest(HttpContextBase context)
{
....
context.Response.Write(builder.ToString());
}
public Mock<HttpResponseBase> MockResponse { get; set; }
...
var outputStream = new MemoryStream();
var filter = new MemoryStream();
//MockResponse.Setup(response => response.OutputStream).Returns(GetMockStream(outputStream).Object);
//MockResponse.Setup(response => response.Filter).Returns(GetMockStream(filter).Object);
MockResponse.Setup(response => response.OutputStream).Returns(() => outputStream);
//MockResponse.SetupSet(response => response.OutputStream = It.IsAny<Stream>()).Returns(() => outputStream);
MockResponse.Setup(response => response.Filter).Returns(() => filter);
MockResponse.SetupSet(response => response.Filter = It.IsAny<Stream>());
MockResponse.SetupSet(response => response.Filter = It.IsAny<ResponseSniffer>());
[TestMethod]
public void TestMethod1()
{
var mockHttpContext = new MoqHttpContext();
var httpContext = mockHttpContext.HttpContext();
var html = @"<html>
<head></head>
<body>
<h1>Hello World</h1>
</body>
</html>";
httpContext.ResponseWrite(html);
httpContext.StreamWrite(httpContext.Response.Filter, html);
var module = new Module();
module.PreRequestHandlerExecute(mockHttpContext.HttpContext());
module.ApplicationBeginRequest(mockHttpContext.HttpContext());
module.ApplicationEndRequest(mockHttpContext.HttpContext());
var responseRead = httpContext.ResponseRead(); //extension method to get output stream
var b = 1; //put breakpoint here
}
最佳答案
让我们看一下Module.ApplicationEndRequest()
方法中的以下语句:
context.Response.Write(builder.ToString());
context.Response
是您在MoqHttpContext.CreateBaseMocks()中设置的模拟:
MockResponse = new Mock<HttpResponseBase>();
// ...
MockContext.Setup(ctx => ctx.Response).Returns(MockResponse.Object);
Write()
方法,然后可以读回相同的数据。模拟是伪造的对象。它的
Write()
方法的默认实现不执行任何操作,并且传递的数据只会丢失。
Response
模拟上设置一个回调,该回调将传递的数据写入流,然后在读取时将其返回。您实际上非常接近它。
MoqHttpContext
类中声明一个流,您将在其中保存数据:
public class MoqHttpContext
{
private readonly MemoryStream _outputStream = new MemoryStream();
// ...
}
CreateBaseMocks()
方法中设置回调:
public MoqHttpContext CreateBaseMocks()
{
// ...
MockResponse = new Mock<HttpResponseBase>();
MockResponse.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(s =>
{
var data = Encoding.ASCII.GetBytes(s);
_outputStream.Write(data, 0, data.Length);
_outputStream.Flush();
_outputStream.Position = 0;
});
// ...
}
inputStream
中将
0
位置设置为
MoqHttpContextExtensions.StreamWrite()
的行,以便附加在
UnitTest1.TestMethod1()
中写入的html数据,而不是被覆盖:
public static HttpContextBase StreamWrite(this HttpContextBase httpContextBase, Stream inputStream, string text)
{
if (inputStream == null) inputStream = new MemoryStream();
var streamWriter = new StreamWriter(inputStream);
inputStream.Position = inputStream.Length;
streamWriter.Write(text);
streamWriter.Flush();
// Remove this line
//inputStream.Position = 0;
return httpContextBase;
}
responseRead
的值,您将看到Http模块附加的数据在那里。
Filter
属性的选项,但是似乎都不正确。用Moq模拟属性获取器的正确方法是:
MockResponse.SetupGet(response => response.Filter).Returns(filter);
response.Filter
的语句,但不要添加上述语句,它不是最终版本。
Module.ApplicationEndRequest()
方法中进行以下检查:
if (context.Response.Filter is ResponseSniffer filter)
{
// ...
context.Response.Filter
是
MemoryStream
而不是
ResponseSniffer
。在
Module
构造函数中调用的setter:
context.Response.Filter = new ResponseSniffer(context.Response.Filter);
Filter
getter返回的值,因为它是一个模拟,当前总是返回您使用
MemoryStream
设置的
SetupGet
实例。要解决此问题,您实际上应该模拟属性行为:保存传递给setter的值,并将其返回到getter中。这是
response.Filter
属性的最终设置:
Stream filter = new MemoryStream();
MockResponse.SetupSet(response => response.Filter = It.IsAny<Stream>()).Callback<Stream>(value => filter = value);
MockResponse.SetupGet(response => response.Filter).Returns(() => filter);
response.Filter
属性的所有其他模拟。
Module
调用的顺序。当前顺序如下:
httpContext.StreamWrite(httpContext.Response.Filter, html);
// ...
var module = new Module();
module.PreRequestHandlerExecute(mockHttpContext.HttpContext());
PreRequestHandlerExecute
用
Response.Filter
的实例设置
ResponseSniffer
。因此,当上面的
httpContext.StreamWrite
被调用时,
httpContext.Response.Filter
实际上保存着
MemoryStream
的实例,而不是
ResponseSniffer
。因此,您应该做的最后一个修复是更改UT主体中语句的顺序:
// ...
var module = new Module();
module.PreRequestHandlerExecute(mockHttpContext.HttpContext());
httpContext.ResponseWrite(html);
httpContext.StreamWrite(httpContext.Response.Filter, html);
module.ApplicationBeginRequest(mockHttpContext.HttpContext());
module.ApplicationEndRequest(mockHttpContext.HttpContext());
// ...
ResponseSniffer
和
Module
。
ResponseSniffer
和
Module
类进行测试。
ResponseSniffer
的最有价值的测试是验证书面数据是否已注册在
RecordStream
中的测试:
[TestClass]
public class ResponseSnifferTests
{
[TestMethod]
public void Write_WritesDataToRecordStream()
{
// Arrange
var inData = new byte[] { 0x01 };
var target = new ResponseSniffer(Mock.Of<Stream>());
// Act
target.Write(inData, 0, inData.Length);
// Assert
target.RecordStream.Position = 0;
var outData = new byte[inData.Length];
int outSize = target.RecordStream.Read(outData, 0, outData.Length);
Assert.AreEqual(inData.Length, outSize);
CollectionAssert.AreEqual(inData, outData);
}
}
Module
类,应进行以下检查:
PreRequestHandlerExecute()
用
Response.Filter
的实例设置
ResponseSniffer
。
ApplicationBeginRequest()
将
Stopwatch
添加到
context.Items
词典。
ApplicationEndRequest()
将请求信息写入响应。
[TestClass]
public class ModuleTests
{
[TestMethod]
public void PreRequestHandlerExecuteShouldSetResponseSnifferAsFilter()
{
// Arrange
Stream filter = null;
Mock<HttpResponseBase> httpResponseMock = new Mock<HttpResponseBase>();
httpResponseMock.SetupSet(response => response.Filter = It.IsAny<Stream>()).Callback<Stream>(value => filter = value);
Mock<HttpContextBase> httpContextStub = new Mock<HttpContextBase>();
httpContextStub.SetupGet(x => x.Response).Returns(httpResponseMock.Object);
var target = new Module();
// Act
target.PreRequestHandlerExecute(httpContextStub.Object);
// Assert
Assert.IsNotNull(filter);
Assert.IsInstanceOfType(filter, typeof(ResponseSniffer));
}
[TestMethod]
public void ApplicationBeginRequestShouldStoreStopwatchInContextItems()
{
// Arrange
var items = new Dictionary<string, object>();
Mock<HttpContextBase> httpContextStub = new Mock<HttpContextBase>();
httpContextStub.SetupGet(x => x.Items).Returns(items);
var target = new Module();
// Act
target.ApplicationBeginRequest(httpContextStub.Object);
// Assert
Assert.IsTrue(items.ContainsKey("X-ResponseTime"));
Assert.IsInstanceOfType(items["X-ResponseTime"], typeof(Stopwatch));
}
[TestMethod]
public void ApplicationEndRequestShouldAddRequestInfoToResponse()
{
// Arrange
Mock<HttpRequestBase> httpRequestMock = new Mock<HttpRequestBase>();
httpRequestMock.SetupGet(x => x.FilePath).Returns("/test");
string writtenData = null;
Mock<HttpResponseBase> httpResponseMock = new Mock<HttpResponseBase>();
httpResponseMock.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(s => writtenData = s);
Mock<HttpContextBase> httpContextStub = new Mock<HttpContextBase>();
httpContextStub.SetupGet(x => x.Request).Returns(httpRequestMock.Object);
httpContextStub.SetupGet(x => x.Response).Returns(httpResponseMock.Object);
httpContextStub.SetupGet(x => x.Items).Returns(new Dictionary<string, object> { ["X-ResponseTime"] = new Stopwatch() });
var target = new Module();
// Act
target.ApplicationEndRequest(httpContextStub.Object);
// Assert
Assert.IsTrue(Regex.IsMatch(writtenData, @"Response Size: \d+ bytes<br/>"));
Assert.IsTrue(Regex.IsMatch(writtenData, @"Module request time: \d+ ms"));
}
}
MoqHttpContext
和
MoqHttpContextExtensions
。另一个好处-如果某些测试失败了,则更容易找出根本原因并加以解决。
关于c# - 使用Response.Filter和Response.Write测试Http模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48888130/
我有一个包含以下内容的简单服务: import { Injectable } from '@angular/core'; import { Http, Response } from '@angula
在我的 Angular-12 应用程序中,我在服务中有以下代码: constructor(private http: HttpClient, private router: Router) {
我是android领域的新手,我想从响应json数组访问每个结果元素,但我无法做到这一点,我试图获取每个元素,但我只得到一个值“rohit1”是第一个元素。请帮助我。 我是 rohit parmar,
我正在用 java 编写 RESTful 服务,但是当我尝试使用 Resource 类时,显示以下错误:类型 Response.Response 构建器不可见。我不明白问题可能是什么,因为我已经导入了
在 Spring 应用程序中,我正在调用第三方服务,我正在发送 XML 请求并获取 XML 响应,当无法将该响应解析为 Java 对象时,我正确地获得了 XML 响应,我收到以下错误: org.spr
我正在发布一个页面 URL 例如 mysite.com/disclaimer/someinfo 此页面显示协议(protocol),如果用户单击同意按钮,则 PDF 文件将作为附件流式传输。 这样做的
我是 Camel 的新手。我一直在尝试将数据(文件中的 Json)提交到网络服务。这是我的代码: public static void main(String args[]) throws E
我有一个 HTTP 执行器类: Future future = service.apply(request).toJavaFuture(); 现在我想删除 ? extends其中的一部分,因为我不想让
我想将我所有的 http header 响应设置为这样的: response.headers["X-Frame-Options"] = "SAMEORIGIN" 我检查了this question ,
我们有两个 channel ,分别是 channelA 和 channelB。 在 channel A中我们有两个目的地 一个。第一个目的地将使用 XML 数据作为输入调用 channelB,并从 c
以下有什么区别 response.status(200).send('Hello World!'); 和这个 response.writeHead(200, {'content-type':'appl
我试图让Foundation在iPhone的浏览器上响应。我已经在手机上尝试过Safari和Chrome,它们都显示了 table 面布局。 但是,在 table 面上,如果缩小浏览器窗口,则会看到布
您好,当我在云代码中运行此作业时,我收到一条错误日志:Failed with: success/error was not called. 定义功能运行良好,但在作业日志中我有此错误日志。请协助我解决
我正在使用ozeki ng短信网关。我无法将任何短信发送到任何手机。请帮助我通过网络发送短信到手机 从客户端检测到一个潜在危险的Request.Form值(textboxError =“。设置此值之后
今天我在 WordPress 中遇到了问题。当我尝试创建一个新页面并在 WordPress 管理部分上传新图像时,我尝试找出解决方案,但我没有得到它......所以经过一个小时的打磨后我得到了一个解决
我过去常常通过刷新和结束来结束对客户端的传输,如下面的代码所示。 Response.Flush(); Response.End(); 但是,Response.End() 将缓冲内容刷新到客户端让我印象
我正在编写一个在单击按钮时显示对话框窗口的函数:这里是与状态和 statusCode 相关的代码段。 if(response.status>300){
从资源清理的角度,为什么会有Response.Close()和Response.Dispose(),哪个更全面(调用另一个)? 最佳答案 在提供这两种方法的情况下,Dispose 的实现应该调用 Cl
在我注意到我的代码可能在以经典模式设置的服务器上运行之前,我一直在使用 Response.Header.Add()。在这种情况下,异常“此操作需要 IIS 集成管道模式”。被提出。 我切换到 Resp
Response.End() 生成 ThreadAbortException。 使用 HttpContext.Current.ApplicationInstance.CompleteRequest 代
我是一名优秀的程序员,十分优秀!