单元测试静态类

时间:2009-06-10 03:25:56

标签: c# .net unit-testing

方案。语言C#,使用VS2008单元测试框架进行单元测试

我有一个静态类,带有静态构造函数和2个方法。 我编写了4种测试方法来测试整个类。 我的静态构造函数有一些重要的初始化。

现在,如果我串联运行所有4个单元测试用例,静态构造函数将是 只在开头叫。在每个测试用例结束时,没有这样的东西

调用静态析构函数,因此构造函数中的状态信息被传递给 下一个单元测试案例也。解决方法是什么。

8 个答案:

答案 0 :(得分:39)

Type staticType = typeof(StaticClassName);
ConstructorInfo ci = staticType.TypeInitializer;
object[] parameters = new object[0];
ci.Invoke(null, parameters);

来自http://colinmackay.scot/2007/06/16/unit-testing-a-static-class/

答案 1 :(得分:12)

最简单的解决方案是在静态类中添加一个“重置”方法,该方法具有破坏它并重构它的等效行为。

在这里使用静态类可能有正当理由。但是,由于静力学不能很好地与单元测试相结合,我通常会寻找替代设计。

答案 2 :(得分:6)

我会将初始化从静态构造函数移动到构造函数调用的方法。通过使此方法内部,您可以从测试中调用此方法以重新初始化该类。

public static class MyClass
{
   public static MyClass()
   {
      initialize();
   }

   internal static void initialize()
   {
      // Do initialization (and cleanup if necessary)
   }

   public static void Method1() {}
   public static void Method2() {}
}

要调用内部方法,您需要使用 InternalsVisibleTo 属性,如this blog中所述。

您也可以将其设为私有,但是您需要使用反射来调用它。

但正如Andrew Shepherd所说,你还应该检查静态类是否是这个类的最佳设计。

答案 3 :(得分:1)

在不知道该类的用法的情况下,仅仅使用该用法是有点棘手的,但不管怎么说还是试试看。对我来说,上面的声音听起来不仅仅是一个测试问题。

静态类(就像单例一样)基本上是全局函数/变量的集合,这在oop中通常是一件坏事。我会说尝试测试测试问题(尽管现在可能是最简单的)只能修复症状而不是问题。

如果您确实需要静态类,或者它似乎是当时解决问题的最简单方法,我建议您先看一下这个设计的方法

答案 4 :(得分:0)

好吧,你没有指定你使用的是哪种语言,但如果有办法从测试文件中打开你的静态类,那么我会为它添加一个假的析构函数,你可以在每个之后调用它测试。这样,'析构函数'就会停留在测试类中,而不会停留在生产代码中。

答案 5 :(得分:0)

您可以使用能够模拟静态类的Typemock's Isolator,因此在每个测试中您都可以“定义”静态操作的方式。

虽然它不是免费产品。

答案 6 :(得分:0)

听起来你正试图测试静态构造函数。这似乎是一个坏主意。

考虑将初始化逻辑提取到单独的(非静态)类中。

为了便于讨论,假设您的静态类名为MySingleton,假设您使用Execute方法创建了一个名为MyInitializer的新类。 MySingleton的静态构造函数可以实例化MyInitializer并调用Execute,它执行所有初始化。

然后您的生产代码可以使用MySingleton,并忽略MyInitializer。另一方面,您的测试可能会忽略MySingleton,并为每个测试快速创建一个新的MyInitializer实例,每次都重新开始。

答案 7 :(得分:0)

为了完整起见,如果需要重置静态类的非公共字段/变量,也可以通过反射来重置。

using System.Reflection; // or Mono.Reflection

public static class MyClass{
    private static string myString;
}

var newValue = "Potatoes";            
var field = typeof(MyClass).GetField("myString", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, newValue); // the first null is because the class is static, the second is the new value