4

How do I setup the unit test if the constructor is private (.NET)?

This is my class:

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

    public static Class2 getInstance()
    {

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

        return x;
    }
}

This is my unit test:

[TestFixture]
public class Class2Tester
{
    private Class2 test;

    [SetUp()]
    public void SetUp()
    {
        // I cant do this. How should I setup this up?
        test = new Class2();
    }
}
Adrian Thompson Phillips
  • 6,893
  • 6
  • 38
  • 69

6 Answers6

5

The answer is: you don't. Not because you can't, but because you shouldn't.

By making the constructor private, you're saying that its behavior is not part of the public API of the class. In this case its behavior either a) doesn't affect the public API of the class which means it doesn't need to be tested. b) more likely, does affect the public API of the class, in which case, write your tests around that public API, not the black-boxed constructor.

jonathan.cone
  • 6,592
  • 2
  • 30
  • 30
  • 2
    Don't be pedantic. In a unit test, creating via the private constructor to decouple the test from the factory methods usually used to create the object is ok. – tvanfosson Feb 23 '09 at 03:54
  • Uhh, yeah, sure it is if you want to break the unit test when you refactor the internals of the constructor. – jonathan.cone Feb 23 '09 at 03:59
  • 2
    Personal preference, I guess. Typically, my default constructors don't have any actual code so there's nothing to break. The factory method would simply create an empty object and assign properties. Decoupling from the factory method allows me to set up just those parts of the object under test. – tvanfosson Feb 23 '09 at 04:04
4

You don't specify a language so my answer will be generic. The typical way to do this is using reflection. You can do it directly in each test or by creating an accessor class that wraps all of the private methods/properties, including the constructor.

An example from C#/.NET

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

Or, more typically, after adding private accessors to your test project

public void MyTest()
{
    MyClass class = ((MyClass)new MyClass_Accessor()).Target;
}
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
3

In java (and this assumes the only constructor is the private default constructor, otherwise checking of the array is required):

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

Then, currentInstance is available for you to use. Typically I'll only do this for code coverage, if I make a constructor private, it's generally to avoid instantiation.

MetroidFan2002
  • 29,217
  • 16
  • 62
  • 80
2

Depends on what you are doing in the private constructor. If you are using a private constructor to disallow creating of an instance of a utility class then I suggest that you throw an illegalaccesserror similar to what you see in EJ2. In that case you can simply test it via reflections that it won't be bypassed.

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

I don't disagree with this type of testing. It can help find places that are accidentally creating an instance of your util class where you didn't mean for it to (serialization/deserialization etc).

It could mean for some nasty surprises too if they were (highly not recommended) stateful.

Tim
  • 21
  • 1
1

I usually don't unit test constructors at all. In this situation, the first thing you should ask yourself is if you really do need to unit test the code in this constructor. Of course the paranoid perfectionist in all of us will come out at times, so if the answer is no, I say just forget about it.

If the answer is yes, I'm of the opinion that there's a good chance that you're doing too much with your constructor and/or your class. Even if this isn't the case, there's a good chance that you can break the code that does need to be unit tested into its own public function.

Granted, there are always exceptions. But I've yet to run into an instance where I had to make a constructor private and I had to unit test it.

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
0

Basically, you should not do that. See this question.

Community
  • 1
  • 1
Fabian Steeg
  • 44,988
  • 7
  • 85
  • 112
  • 1
    That question is talking about testing private methods. He just wants to use the private constructor to set up a test, not test the constructor itself. – tvanfosson Feb 23 '09 at 03:55