简体   繁体   English

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

[英]How to Mock HttpContextBase correctly so my unit tests are working

Given the following function: 赋予以下功能:

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.
}

I'm using a HttpContextBase and an interface for a Unit Of Work, since I know it's easier to unit test than. 我正在为工作单元使用HttpContextBase和接口,因为我知道单元测试比工作起来容易。

Now I'm using Moq to using Mocking functionality in my unit test and I'm struggling with it. 现在,我在单元测试中使用Moq来使用Mocking功能,但我为此感到吃力。

Let's see the variable cliënt: 让我们看一下变量cliënt:

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

I would like to know how to setup my Unit Test(s) by mocking the necessary objects. 我想知道如何通过模拟必要的对象来设置我的单元测试。

Here's my current unit test: 这是我当前的单元测试:

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);

The setup of the httpApplicationMock is failing because context.Object is not a valid parameter but I need to pass in a HttpContext. httpApplicationMock的设置失败,因为context.Object不是有效的参数,但是我需要传递HttpContext。

Can someone give me a little, gentle push in the right direction? 有人可以给我一点点正确方向的推动力吗?

This line fails because Context returns HttpContext type, not HttpContextBase . 该行失败,因为Context返回HttpContext类型,而不是HttpContextBase

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

Creating context as Mock<HttpContext> instance won't help either because it's a sealed class and Moq can't mock sealed classes. 创建context作为Mock<HttpContext>实例也无济于事,因为它是一个密封的类,而Moq无法模拟密封的类。

You can hide implementation details concerning HttpContext behind an interface. 您可以在接口后面隐藏有关HttpContext的实现细节。 Here's blog post that shows you an example: http://volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext 这是为您显示示例的博客文章: http : //volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext

After some further tests I've realized what it wrong. 经过一些进一步的测试,我意识到了问题所在。

First of all, and quite important, I'm using MSTest. 首先,非常重要,我正在使用MSTest。 So the problem does not rely on repository being created in the constructor because for each test that is runt through MSTest, the constructor is executed. 因此,问题不依赖于在构造函数中创建的存储库,因为对于通过MSTest运行的每个测试,都将执行构造函数。 So that's eliminated. 这样就消除了。

After some further inspection, I've realised that, to retrieve the settings from the settingsrepository, I use a class which is instantiated as a Singleton, and that was the problem. 经过进一步检查,我意识到,要从设置存储库检索设置,我使用了一个实例化为Singleton的类,这就是问题所在。

When I run my first file with unit test with a specified setting, all went fine since the setting still needed to be created. 当我使用具有指定设置的单元测试运行我的第一个文件时,由于仍需要创建该设置,因此一切正常。

But in my second file, I use another settings, but since the manager which is responsible for getting the settings is a Singleton, the new settings were not retrieved and instead the settings from the previous one were used. 但是在第二个文件中,我使用了另一个设置,但是由于负责获取设置的管理器是Singleton,因此未检索到新设置,而是使用了前一个设置。

That caused the issue. 这引起了问题。

Anyway, thanks to the persons who have tried to helped me out on this situation. 无论如何,要感谢那些试图帮助我解决这种情况的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 这是模拟HttpContextBase,HttpRequestBase和HttpResponseBase进行单元测试Cookie的正确方法吗? - Is this the correct way to mock HttpContextBase, HttpRequestBase and HttpResponseBase for Unit Testing Cookies? 如何正确进行单元测试 - How to do unit tests correctly 如何为单元测试模拟数据? - How can I mock data for unit tests? 如何在单元测试中模拟 Automapper ProjectTo&lt;&gt; 方法? - How to mock Automapper ProjectTo<> method in Unit Tests? 如何在单元测试中模拟控制器上下文,以便我对字符串函数的部分视图有效? - How do I mock controller context in my unit test so that my partial view to string function works? 如何正确地将我的测试错误添加到堆栈中,以便测试不会停止执行? - How correctly add my tests' errors to a stack so the tests don't stop executing? 在单元测试中模拟 IHttpContextAccessor - Mock IHttpContextAccessor in Unit Tests 如何在单元测试中使用 Mock 对象并仍然使用代码覆盖率? - How can I use Mock Objects in my unit tests and still use Code Coverage? 我如何将HttpContextBase模拟到控制器Web API - how can i mock HttpContextBase to a controller web api 我如何模拟Request.Url.GetLeftPart()以便我的单元测试通过 - How can I mock Request.Url.GetLeftPart() so my unit test passes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM