如何设置私有构造函数?

时间:2009-02-23 03:41:40

标签: c# unit-testing constructor nunit private

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

6 个答案:

答案 0 :(得分:5)

答案是:你没有。不是因为你不能,而是因为你不应该。

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

答案 1 :(得分:4)

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

来自C#/ .NET的示例

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

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

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

答案 2 :(得分:3)

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

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

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

答案 3 :(得分:2)

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

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

我不同意这种类型的测试。它可以帮助找到意外创建util类实例的地方(序列化/反序列化等)。

如果(非常不推荐)有状态,这也可能意味着一些令人讨厌的惊喜。

答案 4 :(得分:1)

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

如果答案是肯定的,我认为您很可能在构建者和/或您的班级上做得太多。即使不是这种情况,也很有可能将需要进行单元测试的代码分解为自己的公共函数。

当然,总有例外。但我还没遇到一个必须将构造函数设为私有的实例,我不得不进行单元测试。

答案 5 :(得分:0)

基本上,你不应该这样做。请参阅this question