此帖与其他两个帖子相关,here和here。我的新单元测试&嘲笑。我有一个测试装置试图模拟包括响应和请求的HttpContext对象。我认为测试代码没有正确设置,因为在调用处理程序后,我立即得到一个错误。我得到的错误是:HttpHandler模拟,单元测试(NUnit)设置问题
UnitTests.UADHandlerFixture.Request_Is_Object: System.NullReferenceException:未将对象引用设置为对象的实例。
在BaseHttpHandler.cs在Abstract.BaseHttpHandler.get_Request():在BaseHttpHandler.cs线21
在Abstract.BaseHttpHandler.get_IsRequestFromUAD():23行
在Handlers.UADTimeHttpHandler.ProcessRequest(HttpContextBase上下文)中UADTimeHttpHandler.cs:线19
在UnitTests.UADHandlerFixture.Request_Is_Object()在UADHttpHanderTests.cs:管线47
测试代码是这样的:
[TestFixture]
public class UADHandlerFixture
{
private Mock<HttpContextBase> _mockHttpContext;
private Mock<HttpRequestBase> _mockHttpRequest;
private Mock<HttpResponseBase> _mockHttpResponse;
private UADTimeHttpHandler _handler;
private WindsorContainer _container;
[SetUp]
public void Init()
{
_mockHttpRequest = new Mock<HttpRequestBase>();
_mockHttpResponse = new Mock<HttpResponseBase>();
_mockHttpContext = new Mock<HttpContextBase>();
_container = new WindsorContainer();
_container.AddComponent<ILogger, FakeLogger>();
_container.AddComponent<IDataRepository, FakeDataRepository>();
_mockHttpContext.SetupGet(x => x.Application[0]).Returns(_container);
_mockHttpContext.SetupGet(x => x.Request).Returns(_mockHttpRequest.Object);
_mockHttpContext.SetupGet(x => x.Response).Returns(_mockHttpResponse.Object);
_handler = new UADTimeHttpHandler();
}
[Test]
public void Request_Is_Object()
{
_handler.ProcessRequest(_mockHttpContext.Object);
}
}
处理程序:
public class UADTimeHttpHandler : BaseHttpHandler
{
public override void ProcessRequest(HttpContextBase context)
{
if (IsRequestFromUAD)
{
Logger.Log("Log stuff");
DataRepository.Write("DB stuff");
ReturnResponse(HttpStatusCode.OK, DateTime.Now.ToString());
}
else
ReturnResponse(HttpStatusCode.BadRequest);
}
}
BaseHandler:
public abstract class BaseHttpHandler : IHttpHandler
{
private HttpContext _httpContext;
private ILogger _logger;
private IDataRepository _dataRepository;
protected ILogger Logger { get { return _logger; } }
protected IDataRepository DataRepository { get { return _dataRepository; } }
protected HttpContext Context { get { return _httpContext; } }
protected HttpRequest Request { get { return _httpContext.Request; } }
protected HttpResponse Response { get { return _httpContext.Response; } }
protected bool IsRequestFromUAD { get { return Request.UserAgent == null ? false : Request.UserAgent.Equals("UAD"); } }
public virtual bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
WindsorContainer container = (WindsorContainer)context.Application[0];
_logger = container.Resolve<ILogger>();
_dataRepository = container.Resolve<IDataRepository>();
_httpContext = context;
ProcessRequest(new HttpContextWrapper(context));
}
protected virtual void ReturnResponse(HttpStatusCode httpStatus)
{
Response.StatusCode = (int)httpStatus;
}
protected virtual void ReturnResponse(HttpStatusCode httpStatus, string response)
{
Response.StatusCode = (int)httpStatus;
Response.Write(response);
}
protected virtual string GetInputStream()
{
using (var reader = new StreamReader(Request.InputStream))
{
return reader.ReadToEnd();
}
}
public abstract void ProcessRequest(HttpContextBase context);
}
嗨,弗兰克。谢谢你的评论。如果BaseHttpHandler实现IHttpHandler,则不应该自动调用ProcessRequest方法?当我在单元测试之外运行此代码时,它工作正常吗? – Matt 2010-08-24 23:30:42
您没有将ProcessRequest标记为虚拟。所以当运行时有一个指向你的类的指针作为BaseHttpRequest时,它会尝试调用BaseHttpRequest.ProcessRequest()。当你的测试有一个指针作为UADTimeHandler时,它会尝试调用UADTimeHandler.ProcessRequest()。所以他们有不同的行为。 – 2010-08-25 00:58:39
嗯,我不知道你为什么看到这种行为,因为运行时将它作为IHttpHandler而不是BaseHttpHandler引用。我想知道如果你的测试的行为不同,如果UADHandlerFixture._handler的类型是IHttpHandler而不是BaseHttpHandler。 – 2010-08-25 01:00:57