如何正确模拟HttpContextBase,以便我的单元测试工作正常

时间:2014-05-27 11:13:41

标签: c# unit-testing mocking moq

给出以下功能:

public static void Write(HttpContextBase contextBase, IUnitOfWork unitOfWork, LogLevel level, string title, string message, params AdditionalProperty[] properties)
{
    // Some variables that are set for writing the logs.
    //      - client: When the HttpContext is null, 'N.A.' is used, otherwise the I.P. address of the requesting computer.
    //      - userIdentifier: When the HttpContext exists and a value is stored in the cookie, the value of the cookie, otherwise an empty guid.
    //      - requestIdentifier: When the context is existing and a request have been made on a controller, a unique value identifying this request, otherwise an empty guid.

    string client = (contextBase.ApplicationInstance == null || contextBase.ApplicationInstance.Context.CurrentHandler == null) ? "N.A." : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
    string userIdentifier = (contextBase.ApplicationInstance != null && contextBase.ApplicationInstance.Context != null && contextBase.ApplicationInstance.Context.CurrentHandler != null && CookieManager.Exists("UserIdentifier")) ? CookieManager.Read("UserIdentifier", Guid.NewGuid().ToString().ToUpper()) : Guid.Empty.ToString();
    string requestIdentifier = (contextBase.ApplicationInstance != null && contextBase.ApplicationInstance.Context != null && contextBase.ApplicationInstance.Context.Cache != null && HttpContext.Current.Cache["RequestIdentifier"] != null) ? HttpContext.Current.Cache["RequestIdentifier"].ToString() : Guid.Empty.ToString();

    // Additional code for processing is done here.
}

我正在使用HttpContextBase和一个工作单元的接口,因为我知道它比单元测试更容易。

现在我正在使用Moq在我的单元测试中使用Mocking功能,我正在努力解决它。

让我们看看变量cliënt:

string client = (contextBase.ApplicationInstance == null || contextBase.ApplicationInstance.Context.CurrentHandler == null) ? "N.A." : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

我想知道如何通过模拟必要的对象来设置我的单元测试。

这是我目前的单元测试:

var context = new Mock<HttpContextBase>();
var httpApplicationMock = new Mock<HttpApplication>();

httpApplicationMock.SetupGet(x => x.Context).Returns(context.Object); --> FAILS
context.SetupGet(c => c.ApplicationInstance).Returns(httpApplicationMock.Object);

httpApplicationMock的设置失败,因为context.Object不是有效参数,但我需要传入HttpContext。

有人可以给我一个小小的,温和的推动方向吗?

2 个答案:

答案 0 :(得分:1)

此行失败,因为Context返回HttpContext类型,而不是HttpContextBase

httpApplicationMock.SetupGet(x => x.Context).Returns(context.Object);

创建context作为Mock<HttpContext>实例也无济于事,因为它是一个密封的类,而Moq不能模拟密封的类。

您可以在界面后隐藏有关HttpContext的实现详细信息。这篇博文向您展示了一个示例:http://volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext

答案 1 :(得分:0)

经过一些进一步的测试后,我意识到它出了什么问题。

首先,非常重要的是,我正在使用MSTest。所以问题不依赖于在构造函数中创建的存储库,因为对于通过MSTest运行的每个测试,都会执行构造函数。所以这已经消除了。

经过一些进一步的检查,我意识到,为了从settingsrepository中检索设置,我使用了一个实例化为Singleton的类,这就是问题所在。

当我使用指定设置运行单元测试的第一个文件时,一切都很顺利,因为仍然需要创建设置。

但是在我的第二个文件中,我使用了其他设置,但由于负责获取设置的管理员是Singleton,因此未检索到新设置,而是使用了前一个设置。

导致了这个问题。

无论如何,感谢那些试图帮助我解决这个问题的人。