Страницы

Поиск по вопросам

четверг, 23 января 2020 г.

Синглтон и тестирование

#java #юнит_тесты #junit


В общем есть следующий код, состоящий из синглтона и класса, использующего его (упрощенная
версия).

public final class Singleton {
    private static Singleton s_instance = new Singleton();

    public static Singleton getInstance(){
        return s_instance;
    }

    public String getString(){
        return "string";
    }

    public String getStringTest(){
        return "string_test";
    }
}


public class SomeClass{
    private String someString;

    public SomeClass(){
        someString = Singleton.getInstance().getString();
    }
}


Синглтон считывает конфигурацию из файла и предоставляет методы для ее получения
компонентами программы (getString() и т.п.). 

Для тестирования работы класса SomeClass мне нужно, чтобы он получил другое значение
при вызове getString(), а именно то, которое вернет getStringTest().

Я хотел бы иметь что-то типа такого, но столкнулся с тем, что не знаю, как создать
mock или spy объект для синглтона:

when(Singleton.getInstance().getString()).thenReturn(Singleton.getInstance().getStringlTest());


Ну и как следствие вопрос: Как можно создать mock или spy объект для синглтона или
как по-другому можно подменить возвращаемое синглтоном значение? Java, jUnit4.
    


Ответы

Ответ 1



Mockito, мне кажется, прекрасно справится с Вашей задачей. Singleton singleton = mock(Singleton.class); when(singleton.getStringTest()).thenReturn("What you need");

Ответ 2



Приведу самый эффективный, пусть и не очень красивый (и очень непопулярный) вариант тестирования Singleton. Шаг 1. Добавьте метод Singleton.setInstance и сделайте конструктор Singleton защищенным: public final class Singleton { private static Singleton s_instance = new Singleton(); public static setInstance(Singleton instance) { s_instance = instance; } // ... } Шаг 2. Мокните класс Singleton любым способом и задайте полученный объект через Singleton.setInstace Шаг 3. Протестируйте класс SomeClass. А когда у вас появится время для выплаты технического долга, выполните еще один шаг: Шаг 4. Проведите рефакториг класса SomeClass, выкинув любое использование метода Singleton.getInstance. Инжектируйте экземпляр Singleton в SomeClass в явном виде.

Комментариев нет:

Отправить комментарий