如何设置私有构造函数?

4

如果构造函数是私有的(.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();
    }
}

你的标题和问题略有不同。你可能想编辑标题以反映你实际提出的问题。 - tvanfosson
你的代码为什么有这么多空行? - Lightness Races in Orbit
6个回答

5
答案是:你不需要这么做。不是因为你不能,而是因为你不应该。
通过将构造函数设为私有,你是在说它的行为不是类的公共API的一部分。在这种情况下,它的行为要么a) 不影响类的公共API,这意味着它不需要被测试。b) 更可能的是,会影响类的公共API,在这种情况下,写测试用例时围绕公共API编写测试,而不是黑盒构造函数。

2
不要太过苛求。在单元测试中,通过私有构造函数创建对象以将测试与通常用于创建对象的工厂方法解耦是可以的。 - tvanfosson
如果你想在重构构造函数的内部时打破单元测试,那么当然可以这样做。 - jonathan.cone
2
个人喜好吧。通常来说,我的默认构造函数没有任何实际代码,因此也就没有什么可以破坏的了。工厂方法只是创建一个空对象并分配属性而已。从工厂方法中解耦允许我仅设置被测试对象的那些部分。 - tvanfosson

4
您没有指定语言,因此我的答案将是通用的。典型的方法是使用反射。您可以在每个测试中直接执行它,也可以创建一个访问器类,包装所有私有方法/属性,包括构造函数。
以下是C#/.NET的示例:
public void MyTest()
{
    MyClass class = typeof(MyClass).GetConstructor( null )
                                   .Invoke( null );
    ...
}

或者,更典型的情况是,在将私有访问器添加到您的测试项目之后。
public void MyTest()
{
    MyClass class = ((MyClass)new MyClass_Accessor()).Target;
}

3
在Java中(假设唯一的构造函数是私有默认构造函数,否则需要检查数组):
Constructor[] constructors = YourClass.class.getDeclaredConstructors();
constructors[0].setAccessible(true);
YourClass currentInstance = (YourClass) constructors[0].newInstance(null);

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


2

取决于你在私有构造函数中的操作。 如果你使用私有构造函数来防止创建实用类的实例,那么建议你抛出一个类似于EJ2中看到的非法访问错误。 在这种情况下,你可以通过反射简单地测试它是否被绕过。

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

我不反对这种类型的测试。它可以帮助找到意外创建实用程序类的地方,例如在序列化/反序列化等操作中。

但是如果它们具有(强烈不建议)状态,则可能会导致一些令人不快的惊喜。


1

我通常不会对构造函数进行单元测试。在这种情况下,您应该首先问自己是否真的需要对此构造函数中的代码进行单元测试。当然,我们所有人中的偏执完美主义者有时会出现,所以如果答案是否定的,我建议就忘了它吧。

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

当然,总有例外。但我还没有遇到过必须将构造函数设置为私有并对其进行单元测试的情况。


0

基本上,你不应该那样做。请参见这个问题


1
那个问题是关于测试私有方法的。他只想使用私有构造函数来设置一个测试,而不是测试构造函数本身。 - tvanfosson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接