2013-08-22 6 views
1

Ive прочитал так много статей об использовании Powermock и Mockito и попробовал так много разных способов, но я все еще не могу понять, как тестировать следующий статический метод.Статический метод тестирования единицы измерения, который использует набор ресурсов

public static Map<String, String> getEntries() { 
    Map<String, String> myEntriesMap = new TreeMap<String, String>(); 
    ResourceBundle myEntries = ResourceBundle.getBundle(ENTRIES_BUNDLE); 
    Enumeration<String> enumList = myEntries.getKeys(); 
    String key = null; 
    String value = null; 
    while (enumList.hasMoreElements()) { 
     key = enumList.nextElement().toString(); 
     value = myEntries.getString(key); 
     myEntriesMap.put(key, value); 
    } 
    return myEntriesMap; 
} 

код является частью (унаследованных) класс, содержащий около 30 статических методов, как это и рефакторинга не вариант. Аналогичным образом в некоторых других статических методах восстанавливаются DBconnections.

Например: Как я издеваюсь над пакетом ресурсов ENTRIES_BUNDLE и unit тестируют этот метод? Я ищу шаблон, который может быть применен, как правило, ко всем статическим методам.

+1

Да, этот метод не является единым проверяемым в его нынешнем виде. Не потому, что это статично, а из-за вызова 'ResourceBundle.getBundle'. Теоретически, вы могли бы сделать это с PowerMock, если бы вам действительно пришлось, хотя рефакторинг был бы намного лучшим вариантом. Но я смотрю на ваш вопрос, и мне интересно, почему вы тестируете модуль устаревшего класса. Разумеется, если это класс наследия, то большая часть возможности воспользоваться модульным тестированием уже прошла? И если вы не можете изменить его, тогда что вы будете делать, если ваше тестирование выявит ошибку? –

+0

Спасибо за ваш ответ. Я полностью согласен с вами в отношении ценности, полученной в результате написания Junits. Дело в том, что у нас есть этот проект, и часть кода распространяется на JUnits, а часть кода - нет.Идея состоит в том, чтобы довести весь код до свиданий с Junits и охватить новую разработку также с помощью единичных тестов. Этот код является старым и проверенным и стабильным, поэтому мы не хотим его реорганизовать (по крайней мере, на данный момент). Но, сказав это и посмотрев на ваш комментарий, было бы очень полезно, если бы вы могли указать мне, как это сделать с Powermock. – user2706486

+0

Я собираюсь прямо обмануть ад для этого, но https://code.google.com/p/powermock/wiki/MockitoUsage13 содержит информацию о том, как издеваться над статическими методами. Около одного экрана сверху. Но, честно говоря, сначала попробуйте Рожерио, если сможете. –

ответ

0

Если вы используете следующие библиотеки: Mockito-все и JMockit сделать это шаги:

Пусть говорят, что вы хотите, чтобы дразнить метод гггг из xxxx.class

@MockClass(realClass = xxxx.class) 
public static class MyClass { 
    @Mock 
    public static void yyyy(){ 
      ...... 
    } 
} 

в тесте :

@Test 
public void test() { 
    Mockit.setUpMock(MyClass.class); 
} 
+0

Чтобы сделать это хорошим ответом, вы должны действительно описать насмешливую структуру, которую вы используете. OP спросил о Mockito и PowerMock - это ни один из них. Что мы должны добавить к нашей сборке, чтобы сделать эту тестовую работу? –

+0

Я использую библиотеки mockito-all и jmockit – cristi

3

Вам не нужно издеваться над методом ResourceBundle.getBundle. Просто создайте файл «.properties» в нужном месте в дереве тестового источника. Это все равно будет хорошим и полезным модульным тестом.

+1

+1 это приятно и чисто. Единственные проблемы, которые я вижу, - это то, что для тестирования требуется другой файл свойств из кода приложения или если разные тесты нуждаются в разных файлах свойств друг от друга. Если это окажется проблемой, вы захотите написать тесты, которые устанавливают объекты Properties, а затем записывать их в «живое» пространство. –

1

У нас была симулятивная проблема, издевающаяся над методом ResourceBundle.getString().

java.util.MissingResourceException: Can't find resource for bundle $java.util.ResourceBundle$$EnhancerByMockitoWithCGLIB$$e9ea44f0, key name

Наша проблема заключалась в том, что метод является окончательным, что делает невозможным для Mockito издеваться метода.

Вместо этого мы использовали этот soultion: https://code.google.com/p/powermock/wiki/MockSystem

Заметьте, что @PrepareForTest ({ClassThatCallsTheSystemClass.class}) НЕ класс ResourceBundle!

7

Используйте ResourceBundle.getBundle (String, ResourceBundle.Control), чтобы получить ResourceBundle для кэширования пакета для данной строки. Вы можете подклассифицировать ResourceBundle.Control, чтобы обеспечить любой тип комплекта, который желает ваше сердце.

@Test 
public void myTest() 
{ 
    // In your Test's init phase run an initial "getBundle()" call 
    // with your control. This will cause ResourceBundle to cache the result. 
    ResourceBundle rb1 = ResourceBundle.getBundle("blah", myControl); 

    // And now calls without the supplied Control will still return 
    // your mocked bundle. Yay! 
    ResourceBundle rb2 = ResourceBundle.getBundle("blah"); 
} 

Вот подклассы Control:

ResourceBundle.Control myControl = new ResourceBundle.Control() 
{ 
    public ResourceBundle newBundle(String baseName, Locale locale, String format, 
      ClassLoader loader, boolean reload) 
    { 
     return myBundle; 
    } 
}; 

И вот один из способов дразнят ResourceBundle (Наполнение TreeMap с ключами/значений по мере необходимости для блока тестов в качестве упражнения для читателя) :

ResourceBundle myBundle = new ResourceBundle() 
{ 
    protected void setParent(ResourceBundle parent) 
    { 
     // overwritten to do nothing, otherwise ResourceBundle.getBundle(String) 
     // gets into an infinite loop! 
    } 

    TreeMap<String, String> tm = new TreeMap<String, String>(); 

    @Override 
    protected Object handleGetObject(String key) 
    { 
     return tm.get(key); 
    } 

    @Override 
    public Enumeration<String> getKeys() 
    { 
     return Collections.enumeration(tm.keySet()); 
    } 
}; 
Смежные вопросы