Как настроить приватный конструктор? - PullRequest
4 голосов
/ 23 февраля 2009

Как настроить модульный тест, если конструктор является частным (.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 ]

5 голосов
/ 23 февраля 2009

Ответ: нет. Не потому что ты не можешь, а потому что не должен.

Делая конструктор приватным, вы говорите, что его поведение не является частью открытого API класса. В этом случае его поведение либо а) не влияет на публичный API класса, что означает, что его не нужно тестировать. б) скорее всего, влияет на общедоступный API класса, и в этом случае пишите свои тесты вокруг этого общедоступного API, а не в конструкторе с черным ящиком.

4 голосов
/ 23 февраля 2009

Вы не указываете язык, поэтому мой ответ будет общим. Типичный способ сделать это - использовать отражение. Вы можете сделать это непосредственно в каждом тесте или создать класс доступа, который обернет все частные методы / свойства, включая конструктор.

Пример из C # /. NET

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

Или, как правило, после добавления частных средств доступа в ваш тестовый проект

public void MyTest()
{
    MyClass class = ((MyClass)new MyClass_Accessor()).Target;
}
3 голосов
/ 23 февраля 2009

В Java (и это предполагает, что единственным конструктором является частный конструктор по умолчанию, в противном случае требуется проверка массива):

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

Тогда для вас доступен currentInstance. Обычно я делаю это только для покрытия кода, если я делаю конструктор частным, это обычно позволяет избежать создания экземпляров.

2 голосов
/ 30 ноября 2010

Зависит от того, что вы делаете в приватном конструкторе. Если вы используете приватный конструктор, чтобы запретить создание экземпляра служебного класса, тогда я предлагаю вам выдать незаконную ошибку, аналогичную той, что вы видите в EJ2. В этом случае вы можете просто проверить это с помощью отражений, которые не будут обойдены.

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

Я не согласен с этим типом тестирования. Он может помочь найти места, которые случайно создают экземпляр вашего класса утилит, для которого вы не хотели (сериализация / десериализация и т. Д.).

Это может означать и некоторые неприятные сюрпризы, если они (настоятельно не рекомендуется) с состоянием.

1 голос
/ 23 февраля 2009

Обычно я вообще не строю модульные тесты. В этой ситуации, первое, что вы должны спросить себя, действительно ли вам нужно выполнить модульное тестирование кода в этом конструкторе. Конечно, параноидальный перфекционист в каждом из нас будет выходить время от времени, поэтому, если ответ будет отрицательным, я скажу, просто забудьте об этом.

Если ответ да, я считаю, что есть большая вероятность, что вы слишком много делаете со своим конструктором и / или вашим классом. Даже если это не так, есть хороший шанс, что вы можете взломать код, который действительно должен быть протестирован модулем, в его собственную публичную функцию.

Конечно, всегда есть исключения. Но мне еще не довелось столкнуться с ситуацией, когда мне пришлось сделать конструктор частным, и мне пришлось его тестировать модулем.

0 голосов
/ 23 февраля 2009

По сути, вы не должны этого делать. См этот вопрос .

...