【问题标题】:Unit Testing Generic Handlers单元测试通用处理程序
【发布时间】:2014-12-28 08:43:20
【问题描述】:

如何使用单元测试在通用处理程序中测试“ProcessRequest”方法的返回值?

 public class Handler1 : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

【问题讨论】:

  • 你的主张是什么?
  • Assert.AreEqual("Hello World", result);响应断言
  • 显示您当前的单元测试代码。 HttpContext 是如何创建的?
  • 我想使用类似 mock 的东西,但问题是 mock 无法创建 httpcontext ! , 它只能模拟 HttpContextBase : var context = new Mock();

标签: asp.net unit-testing generic-handler


【解决方案1】:

尝试使用 SimpleWorkerRequest 创建测试 HttpContext,而不是使用 mock:

SimpleWorkerRequest testRequest = new SimpleWorkerRequest("","","", null, new StringWriter());
HttpContext testContext = new HttpContext(testRequest);
HttpContext.Current = testContext;

然后您可以创建您的处理程序并将 testContext 提供给 ProcessRequest 方法:

var handler = new Handler1();
handler.ProcessRequest(testContext);

然后您可以检查 HttpContext.Current.Response 以对您的测试做出断言。

更新:

我附上了工作单元测试的完整示例(OutputFilterStream 的实现取自here):

    [TestFixture]
    [Category("Unit")]
    public class WhenProcessingRequest
    {
        public class Handler1 : IHttpHandler
        {

            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write("Hello World");
            }

            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }
        }

        public class OutputFilterStream : Stream
        {
            private readonly Stream InnerStream;
            private readonly MemoryStream CopyStream;

            public OutputFilterStream(Stream inner)
            {
                this.InnerStream = inner;
                this.CopyStream = new MemoryStream();
            }

            public string ReadStream()
            {
                lock (this.InnerStream)
                {
                    if (this.CopyStream.Length <= 0L ||
                        !this.CopyStream.CanRead ||
                        !this.CopyStream.CanSeek)
                    {
                        return String.Empty;
                    }

                    long pos = this.CopyStream.Position;
                    this.CopyStream.Position = 0L;
                    try
                    {
                        return new StreamReader(this.CopyStream).ReadToEnd();
                    }
                    finally
                    {
                        try
                        {
                            this.CopyStream.Position = pos;
                        }
                        catch { }
                    }
                }
            }


            public override bool CanRead
            {
                get { return this.InnerStream.CanRead; }
            }

            public override bool CanSeek
            {
                get { return this.InnerStream.CanSeek; }
            }

            public override bool CanWrite
            {
                get { return this.InnerStream.CanWrite; }
            }

            public override void Flush()
            {
                this.InnerStream.Flush();
            }

            public override long Length
            {
                get { return this.InnerStream.Length; }
            }

            public override long Position
            {
                get { return this.InnerStream.Position; }
                set { this.CopyStream.Position = this.InnerStream.Position = value; }
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                return this.InnerStream.Read(buffer, offset, count);
            }

            public override long Seek(long offset, SeekOrigin origin)
            {
                this.CopyStream.Seek(offset, origin);
                return this.InnerStream.Seek(offset, origin);
            }

            public override void SetLength(long value)
            {
                this.CopyStream.SetLength(value);
                this.InnerStream.SetLength(value);
            }

            public override void Write(byte[] buffer, int offset, int count)
            {
                this.CopyStream.Write(buffer, offset, count);
                this.InnerStream.Write(buffer, offset, count);
            }
        }


        [Test]
        public void should_write_response()
        {
            //arrange
            SimpleWorkerRequest testRequest = new SimpleWorkerRequest("", "", "", null, new StringWriter());                
            HttpContext testContext = new HttpContext(testRequest);                
            testContext.Response.Filter = new OutputFilterStream(testContext.Response.Filter);                

            //act
            var handler = new Handler1();
            handler.ProcessRequest(testContext);                
            testContext.Response.End();//end request here(if it is not done in your Handler1)

            //assert
            var result = ((OutputFilterStream)testContext.Response.Filter).ReadStream();
            Assert.AreEqual("Hello World", result);
        }
    }

【讨论】:

  • 完美!但是如何获得“Hello World!”字符串?
  • 事实证明,没有“简单”的方法可以从 HttpContext.Current.Response 中提取响应。但它是doable。您需要创建过滤器来嗅探响应。不幸的是,我今天手头没有 VS 可以尝试。
  • @sadeghhp,我刚刚更新了答案以包含完整的工作单元测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 1970-01-01
  • 2018-09-03
  • 2011-06-23
  • 1970-01-01
  • 2018-07-22
  • 1970-01-01
相关资源
最近更新 更多