【问题标题】:How to setup private constructor?如何设置私有构造函数?
【发布时间】:2010-10-09 06:05:44
【问题描述】:

如果构造函数是私有的 (.NET),我如何设置单元测试?

这是我的课:

public class Class2
{
    // Private constructor.
    private Class2()
    {
    }

    public static Class2 getInstance()
    {

        if (x == null)
        {
            x= new Class2();
        }

        return x;
    }
}

这是我的单元测试:

[TestFixture]
public class Class2Tester
{
    private Class2 test;

    [SetUp()]
    public void SetUp()
    {
        // I cant do this. How should I setup this up?
        test = new Class2();
    }
}

【问题讨论】:

  • 您的标题和您的问题略有不同。您可能需要编辑标题以反映您提出的实际问题。
  • 为什么你的代码中有这么多空行?

标签: c# unit-testing constructor nunit private


【解决方案1】:

您没有指定语言,因此我的回答将是通用的。执行此操作的典型方法是使用反射。您可以在每个测试中直接执行此操作,也可以通过创建一个包含所有私有方法/属性(包括构造函数)的访问器类来执行此操作。

来自 C#/.NET 的示例

public void MyTest()
{
    MyClass class = typeof(MyClass).GetConstructor( null )
                                   .Invoke( null );
    ...
}

或者,更常见的是,在您的测试项目中添加私有访问器之后

public void MyTest()
{
    MyClass class = ((MyClass)new MyClass_Accessor()).Target;
}

【讨论】:

    【解决方案2】:

    基本上,您不应该这样做。见this question

    【讨论】:

    • 那个问题是关于测试私有方法。他只是想用私有构造函数设置测试,而不是测试构造函数本身。
    【解决方案3】:

    答案是:你不知道。不是因为你不能,而是因为你不应该。

    通过将构造函数设为私有,您是在说它的行为不是类的公共 API 的一部分。在这种情况下,它的行为 a) 不会影响类的公共 API,这意味着它不需要进行测试。 b) 更有可能确实会影响类的公共 API,在这种情况下,围绕该公共 API 编写测试,而不是黑盒构造函数。

    【讨论】:

    • 不要学究气。在单元测试中,通过私有构造函数创建,将测试与通常用于创建对象的工厂方法解耦。
    • 嗯,是的,如果你想在重构构造函数的内部时打破单元测试,那肯定是这样。
    • 个人喜好,我猜。通常,我的默认构造函数没有任何实际代码,因此没有什么可破坏的。工厂方法将简单地创建一个空对象并分配属性。与工厂方法解耦允许我只设置被测对象的那些部分。
    【解决方案4】:

    在 java 中(假设唯一的构造函数是私有默认构造函数,否则需要检查数组):

    Constructor[] constructors = YourClass.class.getDeclaredConstructors();
    constructors[0].setAccessible(true);
    YourClass currentInstance = (YourClass) constructors[0].newInstance(null);
    

    然后,currentInstance 可供您使用。 通常我只会为代码覆盖这样做,如果我将构造函数设为私有,通常是为了避免实例化。

    【讨论】:

      【解决方案5】:

      我通常根本不对构造函数进行单元测试。在这种情况下,您应该问自己的第一件事是您是否真的需要对这个构造函数中的代码进行单元测试。当然,我们所有人中的偏执完美主义者有时会出来,所以如果答案是否定的,我说算了吧。

      如果答案是肯定的,我认为你很有可能对构造函数和/或类做了太多事情。即使不是这种情况,您也很有可能将确实需要进行单元测试的代码分解为它自己的公共函数。

      当然,总会有例外。但是我还没有遇到一个实例,我必须将构造函数设为私有并且必须对其进行单元测试。

      【讨论】:

        【解决方案6】:

        取决于您在私有构造函数中所做的事情。 如果您正在使用私有构造函数来禁止创建实用程序类的实例,那么我建议您抛出一个类似于您在 EJ2 中看到的非法访问错误。 在这种情况下,您可以简单地通过不会被绕过的反射来测试它。

        @Test(expected = InvocationTargetException.class)
        public void privateConstructor() throws Exception {
            final Constructor<Keys> myConstructor = Keys.class.getDeclaredConstructor();
            myConstructor.setAccessible(true);
            myConstructor.newInstance();
        }
        

        我不反对这种类型的测试。它可以帮助找到意外创建 util 类的实例的地方,而您并不打算这样做(序列化/反序列化等)。

        如果它们(强烈不推荐)是有状态的,也可能意味着一些令人讨厌的惊喜。

        【讨论】:

          猜你喜欢
          • 2011-10-11
          • 1970-01-01
          • 2011-04-20
          • 2013-08-28
          • 2019-10-16
          相关资源
          最近更新 更多