- 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/
我应该在 Angular 应用程序中使用哪个,为什么? array.filter(o => o.name === myName); 或 $filter('filter')(array, {name:
以下两个调用是否解析为 Django 中的等效 SQL 查询? 链接多个调用 Model.objects \ .filter(arg1=foo) \ .filter(arg2=bar) \ ... 将
我正在尝试在 hbase-1.0.0 上运行 completebulkload。但是遇到错误, "java.lang.NoClassDefFoundError: org/apache/hadoop/h
我从这篇文章中学习了“树”和“索引”:Learning Git Internals by Example 但是当谈到“git filter-branch”命令时,我不知道“--tree-filter”
我正在尝试构建我的自定义过滤器以进行身份验证,但是当我尝试运行我的 WebAPI 解决方案时遇到了这个问题: The given filter instance must implement on
我想保留一个过滤器函数的列表,并通过返回true的过滤器来标记这些项。这是接近但不完全。。主要问题是std::stringify!总是返回“ADF”,可能是我声明为ADF的变量名。。第二个问题是,在定
我想保留一个筛选器函数列表,并通过返回True的筛选器来标记这些项目。这已经很接近了,但还不完全是。。主要问题是std::stringify!总是返回“ADF”,可能是我声明为ADF的变量名。。第二个
我尝试在 graphql 查询中使用 where: filter 但不幸的是我遇到了一些错误。我做错了什么? shoeposts { data { attributes(where: {s
几周以来,我一直在使用 Zend Framework 2,尽管在线文档非常不完整,但我还是设法建立了我的网站的初稿。 不幸的是,我在尝试实现 Zend\Filter\File\Rename 过滤器的自
我正在尝试在 APC 中使用 apc.filter 等功能。但是我所做的一切都不起作用 我应该完成 2 项任务。 1)需要包含1个目录用于缓存。我的代码在apc.ini apc.cache by de
我想使用一个可能返回 Err 的过滤器函数结果,并将其冒泡到包含函数: mycoll.into_iter() .filter(|el| { if el == "bad" { E
每个 Controller 都应该有方法filters(),在那里你可以指定一些类,我想知道,这些类是如何被框架包含的?这些类是如何配置的,以及何时配置,也许有人可以给我一个使用filters()并包
我想在一维信号上使用巴特沃斯滤波器。在 Matlab 中,脚本如下所示: f=100; f_cutoff = 20; fnorm =f_cutoff/(f/2); [b,a] = butter
我想比较两个列表,以便找到第一个列表中不在第二个列表中的值并返回它们。提前谢谢大家代码返回:不再支持过滤器有没有其他方法可以做到这一点 MATCH (cu:Customer{name: "myCust
在 Android 应用程序中,我有一个通用设置 -- 一个带有 ArrayAdapter 的 ListView。在某一时刻,我调用了适配器的 getFilter().filter() 方法,它很好地
所以我有如下数据: [ { "id": 0, "title": "happy dayys", "owner": {"id": "1", "username
阅读Mastering Web Development with AngularJS ,我正在尝试创建并使用一个使用 $filter 模块/关键字的新过滤器。 HTML
所以我的理解是 halt 命令应该停止当前过滤器中的请求,但它似乎继续。下面是一个非常简单的 Sinatra 应用程序,演示了这一点。 服务器.rb require 'sinatra' before
我正在尝试将散列传递给 URL 以设置 UIkit 过滤器。 All
我正在使用 django-filter应用程序。但是有一个问题我不知道如何解决。它几乎与 django 文档中描述的完全相同: https://docs.djangoproject.com/en/1.
我是一名优秀的程序员,十分优秀!