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

Я использовал ВЛАДЕЛЬЦЕ Java для конфигурации на основе свойств.

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

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

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

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

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

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

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

1 ответ

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

Вы можете иметь изменяемые объекты конфигурации. Нет PITA, когда вы читаете руководство.

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

Если вы знаете принципы SOLID, интерфейсы очень легко тестировать, и с ними работать во время тестирования.

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, но существует множество аналогичных фреймворков для тестирования.

Проверьте, что такое MockObjects, что такое внедрение зависимостей и разделение интерфейса.

Я бы не хотел передавать конфиг как зависимость в каждом классе.

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

То же самое относится к вызову фабрики конфигурации в каждом классе

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

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

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

Две вещи:

  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);
    
Другие вопросы по тегам