简体   繁体   English

如何对依赖于HttpContext.GetGlobalResourceObject的类进行单元测试?

[英]How do I unit test a class that relies on HttpContext.GetGlobalResourceObject?

I'm trying to add tests to a webforms project. 我正在尝试将测试添加到webforms项目中。 There's a static method to grab lines from resource files. 有一种静态方法可以从资源文件中获取行。 One of the classes I'm trying to test, relies on grabbing text from the resource file. 我正在尝试测试的其中一个类依赖于从资源文件中获取文本。

public static class MyStaticClass {
    public static string getText(String name)
    {
        String s = HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
        return s;
    }
}

public class ClassUnderTest
{
    // returns: "Hey it's my text"
    private string _eg = MyStaticClass.getText("label_in_resources.resx_file")
}

class UnitTests
{
    [Test]
    public void TestMyClass()
    {
        ClassUnderTest _cut = new ClassUnderTest();
        // errors out because ClassUnderTest utilizes getText
        // which requires HttpContext.GetGlobalResourceObject
        // ... other stuff
    }
}

Note: these are simplistic examples. 注意:这些是简单的例子。

The issue is that I get a Test Failed with the message: 问题是我得到一个测试失败的消息:

Message: System.NullReferenceException : Object reference not set to an instance of an object. 消息:System.NullReferenceException:未将对象引用设置为对象的实例。

With my sleuthing, I've determined that this is because HttpContext is null during these tests. 通过我的调查,我确定这是因为在这些测试期间HttpContext为null。

I've looked at quite a few SO posts on mocking HttpContext but I don't think that I fully understand what exactly they're doing as they're typically dealing with MVC and not Webforms. 我看过很多关于模仿HttpContext帖子,但我不认为我完全理解他们究竟在做什么,因为他们通常处理MVC而不是Webforms。 Still most of them use HttpContextBase and/or HttpContextWrapper but again, I'm not sure how to implement them. 他们中的大多数仍然使用HttpContextBase和/或HttpContextWrapper但是我再也不知道如何实现它们。

Also - I'm not directly testing the getText method. 另外 - 我不是直接测试getText方法。 I know it works. 我知道它有效。 I'm testing a class that uses it. 我正在测试一个使用它的类。 Will mocking the HttpContext even help in this situation? 在这种情况下,嘲笑HttpContext会有帮助吗?

I do realize that this is sort of a hybrid of a unit test / integration test, so if this isn't the best way, I'm all ears... or.. eyes rather. 我确实意识到这是一种单元测试/集成测试的混合体,所以如果这不是最好的方式,我会全神贯注......或者......而是眼睛。

Edit 编辑

For now, I modified my getText method to return the key (name) if the result of HttpContext.GetGlobalResourceObject is null. 现在,如果HttpContext.GetGlobalResourceObject的结果为null,我修改了我的getText方法以返回键(name)。 Then I updated my tests to expect the key instead of the value. 然后我更新了我的测试以期望密钥而不是值。 It's not ideal, but it works and allows me to continue. 这不是理想的,但它有效,并允许我继续。 If there's a better way, please let me know. 如果有更好的方法,请告诉我。

public static class MyStaticClass {
    public static string getText(String name)
    {
        String s = HttpContext.GetGlobalResourceObject("MyResources", name);
        return s != null ? s.ToString() : name;
    }
}

Original answer with Fakes (see below for dealing with removing static) Fakes的原始答案(有关去除静电的信息,请参见下文)

So there's one caveat that I completely forgot about until I just tried to do this. 所以有一个警告,我完全忘记了,直到我试图这样做。 I am pretty sure Fakes still requires Enterprise version of VS. 我很确定Fakes仍然需要VS的企业版。 I don't know if there's a way to get it to work with NUnit, but when you aren't able to change the code sometimes you have to just deal with it. 我不知道是否有办法让它与NUnit一起工作,但是当你无法改变代码时,你必须处理它。

Here's an example of Shimming your static method. 这是一个Shimming静态方法的示例。 You don't need to worry about HttpContext (yet) since you aren't using it directly. 你不需要担心HttpContext(还),因为你没有直接使用它。 Instead you can Shim your getText(string) method. 相反,你可以Shim你的getText(string)方法。

Actual Business Project 实际业务项目

namespace FakesExample
{
    public class MyStaticClass
    {
        public static string GetText(string name)
        {
            throw new NullReferenceException();
        }
    }
}

Your Unit Test Project 你的单元测试项目

using System;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FakesExampleTests
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            using (ShimsContext.Create())
            {
                FakesExample.Fakes.ShimMyStaticClass.GetTextString = (s) =>
                {
                    return "Go away null reference";
                };

                Console.WriteLine(FakesExample.MyStaticClass.GetText("foo"));
            }
        }
    }
}

I actually ran this so I know it works. 我实际上跑了这个,所以我知道它有效。 What happens is that even though GetText will always throw a NullReferenceException when called, our Shim of it returns our own custom message. 会发生的是,即使GetText在调用时总是抛出NullReferenceException,我们的Shim也会返回我们自己的自定义消息。

You may have to make a Visual Studio Test Project. 您可能必须进行Visual Studio测试项目。

In your Unit Test project, right-click your reference and say "Add Fakes". 在单元测试项目中,右键单击您的引用并说“添加假”。 It will generate all of the Shims and Stubs for your assembly. 它将为您的装配生成所有垫片和短柱。


Process of removing the static 去除静电的过程

The best solution is to actually work towards removing the static. 最好的解决方案是实际去除静电。 You've already hit one major reason to not use them. 你已经找到了不使用它们的一个主要原因。

Here's how I would go about removing the static and removing the dependency on HttpContext 这是我如何去除静态和删除对HttpContext的依赖

public interface IResourceRepository
{
    string Get(string name);
}

public class HttpContextResourceRepository : IResourceRepository
{
    public string Get(string name)
    {
        return HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
    }
}

public class MyFormerStaticClass
{
    IResourceRepository _resourceRepository;

    public MyFormerStaticClass(IResourceRepository resourceRepository)
    {
        _resourceRepository = resourceRepository;
    }

    public string GetText(string name)
    {
        return _resourceRepository.Get(name);
    }
}

I would then leverage Dependency Injection to handle the creation of my HttpContextResourceRepository and MyStaticClass (which should probably also be interfaced) in the actual business code. 然后,我将利用依赖注入来处理在实际业务代码中创建我的HttpContextResourceRepositoryMyStaticClass (可能也应该是接口)。

For the unit test, I would mock the implementation 对于单元测试,我会模拟实现

[TestFixture]
public class UnitTest1
{
    [Test]
    public void TestMethod1()
    {
        var repoMock = new Mock<IResourceRepository>();
        repoMock.Setup(repository => repository.Get("foo")).Returns("My Resource Value");

        var formerStatic = new MyFormerStaticClass(repoMock.Object);
        Console.WriteLine(formerStatic.GetText("foo"));
    }
}

Going this route, you can create any number of IResourceRepository implementations and swap them whenever you want. 走这条路线,您可以创建任意数量的IResourceRepository实现并随时交换它们。

暂无
暂无

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

相关问题 如何使用HttpContext.GetGlobalResourceObject? - How to work with HttpContext.GetGlobalResourceObject? 类库中不存在HttpContext.GetGlobalResourceObject - HttpContext.GetGlobalResourceObject not exist in Class Library HttpContext.GetGlobalResourceObject始终为类库中的null - HttpContext.GetGlobalResourceObject Always null from Class Library 如何在应用程序中使用的javascript(.js)文件中访问HttpContext.GetGlobalResourceObject()? - How I access HttpContext.GetGlobalResourceObject() in javascript(.js) file which is used in my application? 如何在C#中创建字符串HttpContext.GetGlobalResourceObject(@“ languagetext”,“ PersonalReportFrench”)? - How to create string HttpContext.GetGlobalResourceObject(@“languagetext”,“PersonalReportFrench”) in C#? HttpContext.GetLocalResourceObject和HttpContext.GetGlobalResourceObject - HttpContext.GetLocalResourceObject and HttpContext.GetGlobalResourceObject 模拟HttpContext.GetGlobalResourceObject()返回null - Mocking HttpContext.GetGlobalResourceObject() returns null 使用Moq在NUnit中模拟HttpContext.GetGlobalResourceObject - Mocking HttpContext.GetGlobalResourceObject in NUnit with Moq 如何编写依赖于文件系统事件的单元测试? - How do I write a unit test that relies on file system events? 如何对依赖于 HttpContext.Current 和 Sitecore.Context 的类进行单元测试? - How do I unit test a class that depends on HttpContext.Current and Sitecore.Context?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM