2016-09-27 9 views
1

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

public class SiteTranslator { 
    Integer id; 
    //Other fields 
} 

public class SiteUtil { 

    private static SiteTranslator siteTranslator = getSiteTranslator(); 

    private static SiteTranslator getSiteTranslator() 
    { 
    SiteTranslator siteTranslator; 
    //Logic involving network call 
    return siteTranslator; 
    } 

    private static String getEnvironment() 
    { 
    String env = ""; 
    //Logic 
    return env; 
    } 

    public static int getParent(int siteId) 
    { 
    int parentId = 0; 
    //Logic using siteTranslator from getSiteTranslator() 
    return parentId; 
    } 
} 


public class SiteUtilTest { 
    @Test 
    public void test1() 
    { 
    try 
    { 
     PowerMockito.suppress(SiteUtil.class.getMethod("getSiteTranslator")); 
     BDDMockito.given(SiteUtil.getParent(1)).willReturn(6); 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 
} 

Объект SiteTranslator мы получаем от getSiteTranslator() метод используется моей общественной функции GetParent() , Поскольку для getSiteTranslator() требуется сетевой вызов, его необходимо подавить. Я же получаю следующую ошибку

java.lang.NoSuchMethodException: SiteUtil.getSiteTranslator() 

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

+0

Возможный дубликат [Возможно ли частичное издевательство над частными статическими методами в PowerMock?] (Http://stackoverflow.com/questions/9719919/is-it-possible-to-use-partial-mocking-for -private-static-methods-in-powermock) – Turing85

ответ

2

На самом деле вам не нужен нужен Powermockito для достижения того, что вам нужно.

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

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

  • Удалить static отборочные
  • инъекции Использование зависимостей

После такой рефакторинг, вы в конечном итоге с чем-то вроде этого (не надоедать!):

public class SiteUtil { 
    private SiteTranslator siteTranslator; 

    public SiteUtil(SiteTranslator siteTranslator) { 
     this.siteTranslator = siteTranslator; 
    } 

    public int getParent(int siteId) { 
     int parentId = 0; 
     // Logic using siteTranslator 
     return parentId; 
    } 

    ... 
} 

Нет ж вы можете проверить это так:

public class SiteUtilSpec { 
    private final SiteTranslator defaultTranslator = new DummySiteTranslator(); 

    @Test 
    public void itShouldReturnTheSixthSiteWhenWeProvideTheFirstParent() { 
     SiteUtil site = new SiteUtil(defaultTranslator); 

     int parentId = site.getParent(1); 

     assertEquals(6, parentId); 
    } 
} 

DummySiteTranslator поддельный объект (может быть, это вложение кучу закодированных переводов полезные для тестирования), но дело в том, что этот объект никогда не любой сетевой вызов! Обеспечение его использования безопасным и быстрым (идеально подходит для тестирования).

+0

Я получаю то, что вы говорите, но siteTranslator построен с данными, которые он извлекает по сети. Поскольку это дорогостоящая операция, я могу сделать это только один раз в своем приложении (и хранить эти данные внутри siteTranslator), следовательно, статический характер.Я не могу позволить себе создавать новый объект SiteUtil каждый раз, когда мне нужно вызвать getParent. –

+1

@PranavKapoor Я прекрасно понял, что реальный «SiteTranslator» стоит дорого, и это совершенно нормально. Но если вы создадите новый 'SiteUtil' с« DummySiteTranslator », это не проблема (не задействован« SiteTranslator »!). В производственном коде вы все же можете построить только один «SiteUtil» с реальным «SiteTranslator». – Spotted

+0

@PranavKapoor Это ответ, на который нужно пойти. Вам не нужен Powermock; и когда вам это не нужно: не используйте его. Это так просто. – GhostCat

1

Ответ на вопрос «Пятнистый» уже забивает его, поскольку основная проблема заключается в следующем: вы создали жесткий код для абсолютно нет причина.

Использование таких внутренних статических вызовов просто делает вашу программу трудной для тестирования; и удивление: оно также делает твердым для поддержания, улучшения, повторного использования. Тот факт, что вам нужно обратиться к Powermock, очень часто является показателем того, что ваш производственный код плохой. Теперь вы можете выбрать между , используя PowerMock, чтобы «исправить» эту проблему; или действительно устранить проблему, изменив ваш производственный код - это просто плохая практика для решения проблем, как это делает ваш примерный код!

Итак, другой реальный урок здесь: вы хотите потратить некоторое время, чтобы научиться писать код, который не имеет таких проблем; например, наблюдая за этими videos.