Тестирование с java-владельцем aeonbits

Я использую Java OWNER для конфигурации на основе свойств.

Я создал статический метод

public static final ApplicationConfiguration config = ConfigFactory.create(ApplicationConfiguration.class,
        System.getProperties(), System.getenv());

и я импортирую класс везде, где мне нужен conf.

Излишне говорить, что модульное тестирование - это PITA. Я не смог найти хороший способ переопределить значения в конфигурации.

Я бы не хотел передавать конфигурацию как зависимость в каждом классе. Это добавляет много многословия и не имеет смысла с точки зрения дизайна. То же самое относится к вызову фабрики конфигурации в каждом классе

ApplicationConfiguration config = ConfigFactory.create(ApplicationConfiguration.class,
        System.getProperties(), System.getenv());

Есть ли у вас предложения? есть лучшая практика?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
1 092
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Две вещи:

  1. Вы можете создать класс, который предоставляет свойства, и все пользователи будут его использовать:

    public class PropertiesAccessor {
    
       private static MyConfiguration mMyConfig = ConfigFactory.create(MyConfiguration.class);
    
       private PropertiesAccessor() 
          // No need to allow instantiation of this class
       }
    
       /**
        * Get properties for this application
        *
        * @return Properties
        */
       public static MyConfiguration getProperties() {
          return mMyConfig;
       }
    
       // for unit testing
       @VisibleForTesting
       public static void setProperties(MyConfiguration config) {
          mMyConfig = config;
       }
    }
    

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

    PropertiesAccessor.getProperties()
    
  2. Обратите внимание, что есть метод для тестирования setProperties (). Есть разные способы использовать этот метод. Вы можете создать тестовый файл свойств, загрузить его, а затем вызвать метод setProperties (). Мне нравится использовать такой служебный метод:

    public static void initProperties(String fileName) {    
    
       Properties testProperties = new Properties();    
    
       File file = new File(fileName);
       FileInputStream stream = null;   
       try {    
          stream = new FileInputStream(file);   
          testProperties.load(stream);  
       } catch (IOException e) {    
          // Log or whatever you want to do
       } finally {  
          if (stream != null) {
          try { 
             stream.close();    
       } catch (IOException e) {    
         // Log or whatever you want to do; 
       }    
    
       MyConfiguration config = ConfigFactory.create(MyConfiguration.class, testProperties);    
       PropertiesAccessor.setProperties(config);
    }
    

    Затем у вас могут быть различные файлы свойств.

    Или, если вы просто хотите установить несколько свойств, сделайте следующее:

     Properties testProperties = new Properties();
     testProperties.setProperty("key1", "data1");
     testProperties.setProperty("key2", "data2");
     final MyConfiguration myConfig = ConfigFactory.create(MyConfiguration.class, testProperties);
     PropertiesAccessor.setProperties(myConfig);
    

Needless to say, unit testing is a PITA. I couldn't find a good way of override the values in the configuration.

У вас могут быть объекты конфигурации Мутабельный. Нет PITA, когда вы читаете руководство.

Но есть подходы получше.

Когда вы знаете ТВЕРДЫЕ принципы, интерфейсы очень легко тестировать и с ними справляться во время тестирования.

import static org.mockito.Mockito.*;

MyConfig cfg = mock(MyConfig.class); // mock object
when(cfg.myConfigurationThing()).thenReturn("whateverYourObjectNeeds");

ObjectThatYouNeedToTest targetObject = 
    new ObjectThatYouNeedToTest(cfg); // Dependency Injection 
                                   // see: http://wiki.c2.com/?ConstructorInjection

assertEquals("expected result", targetObject.whateverYouNeedToTest());

// then you can also verify interactions:

verify(cfg, times(1)).myConfigurationThing();

В приведенном выше фрагменте показан пример Mockito, но существует множество аналогичных сред тестирования.

Проверьте, что такое Макетные объекты, что такое Внедрение зависимости и Разделение интерфейсов.

I would like to avoid passing the config as a dependency in every class.

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

Same applies for calling the config factory in every class

Вызывать фабрику конфигураций в каждом классе - плохая идея. Возможно, вы сможете разделить свой файл конфигурации на множество компонентов для конкретных компонентов. Это один путь (мой путь).

Но если вам нужен один огромный файл конфигурации (что не является моим любимым подходом), ваши интерфейсы конфигурации не обязательно должны соответствовать одной и той же структуре: вы можете иметь несколько интерфейсов конфигурации компонентов, читающих из одного файла: это не лучший вариант, если вы используете горячую перезагрузку, и я, вероятно, мог бы сделать больше для модульного построения объектов конфигурации в дереве вложенных интерфейсов конфигурации. Но эй, я сделал это в свободное время для себя и поделился им бесплатно; если люди делают что-то не так, как я, и нуждаются во мне, чтобы поддержать то, как они работают, возможно, они могли бы поддержать разработку, внося хороший код, или нанять мое время, чтобы улучшить его.

Извините за PITA.

Привет, Луиджи, спасибо за лекцию. всего пара комментариев. Интерфейсы очень легко тестировать, верно, но я имею дело со статическим методом. Это означает, что мне нужно имитировать каждый доступ к свойству, как вы предложили. И это не идеально во время интеграционного тестирования. Существуют фреймворки, которые хорошо справляются с этим сценарием (например, загрузка Spring).

oroblam 04.09.2019 16:53

Очевидно, есть способы обойти это, но я искал более элегантный способ.

oroblam 04.09.2019 16:58

Другие вопросы по теме