Как сделать код, который использует глобальные динамические свойства, тестируемым модулем? - PullRequest
2 голосов
/ 08 июня 2019

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

Для всех таких сценариев я обычно пишу так:

''' 
void someMethod(Data data){
  if(DynamicProperty.getValue("OK"))
    // Do Something

}

DynamicPropery - это синглтон, который периодически обновляет кеш из БД.
Проблема в том, что модульное тестирование немного сложнее, до сих пор я использовал Jmockit , чтобы обойти это - и все работает отлично.
Но мне было интересно, может ли быть лучший способ написать такой метод, который будет проще для модульного тестирования.

Ответы [ 3 ]

3 голосов
/ 08 июня 2019

Вы можете изолировать весь поиск свойств в некотором виде PropertyResolverBean, а затем добавить это в свои SUT и заменить статические вызовы:

private PropertyResolverBean injectedPropertyResolverBean;

void someMethod(Data data){
  if(injectedPropertyResolverBean.getValue("OK"))
    // Do Something

}

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

В конце вы получите более понятный, читаемый и тестируемый код, который следует правилу SRP.

2 голосов
/ 08 июня 2019

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

private DynamicProperty dynamicProperty;

public MyClass(DynamicProperty dynamicProperty){
   this.dynamicProperty = dynamicProperty;           
}

void someMethod(Data data){
  if(dynamicProperty.getValue("OK"))
    // Do Something
}

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

0 голосов
/ 08 июня 2019

Самый простой способ - извлечь значение заранее и передать его при необходимости.

void someMethod(Data data,SomeProperty dynamicProperty){
  if( dynamicProperty whatever)
    // Do Something
}

тогда ваш код вызова становится:

SomeProperty dynamicProperty = DynamicProperty.getValue("OK");    
someMethod(data, dynamicProperty);

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

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

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

...