2017-02-23 38 views
1
public class Manager { 
    private static url = SomeService.get(); 
    public void method() { 
     .... 
    } 
} 

@RunWith(MockitoJUnitRunner.class) 
public class ManagerTest { 
    @InjectMocks 
    Manager manager = new Manager(); 
    @Test 
    public void testMethod(){ 
     manager.method(); 
    } 
} 

Когда я попытался InjectMock Manager класса, я обнаружил, что статическая переменная url является недействительной и не инициализируются в testMethod(). Кто-нибудь дал мне знать, где я сделал это неправильно?Mockito: почему частная переменная не загружается в классный класс?

+0

'частных статического URL = SomeService.get()' не имеет какой-либо тип данных. каков будет тип данных вашей переменной 'url'? – msagala25

+0

Используя Mockito, вы будете обеспечивать насмешливое поведение при доступе к свойствам. В случае статических переменных вы можете использовать PowerMock. – Barath

+0

@ LKTN.25, когда я отлаживаю код, SomeService.get(); вернет строку. Я полагаю, проблема в том, что она никогда не загружается. – c2340878

ответ

1

В Mockito, @InjectMocks не делает никакой магии. Он просто создает аннотированный System-Under-Test (SUT) в случае, если вы не создаете его самостоятельно, и вызывайте соответствующие сеттеры, чтобы вставлять mocks в SUT.

Вернитесь к своему коду, нет способа, с помощью которого Mockito может перейти, чтобы изменить поведение вашего private static final SomeUrl url = SomeService.get();. Это просто ваш настоящий SomeService.get() is null.

Есть, конечно, способы обхода его (используя Powermock или другую насмешливую библиотеку, такую ​​как JMockIt и т. Д.). Самая большая проблема здесь заключается в том, что ваш код не написан, чтобы его легко тестировать. Попробуйте сделать такой рефакторинг как:

  1. В таком случае не используйте static.
  2. Избегайте создания зависимостей (которые вам нужно высмеять) внутри SUT. Зависимости следует вводить.

Так что ваш код будет выглядеть

public class Manager { 
    private SomeUrl url; 

    public void setUrl(SomeUrl url) { this.url = url; } 

    public void method() { 
     doSomethingOnUrl(this.url.getUrlString()); 
    } 
} 

@RunWith(MockitoJUnitRunner.class) 
public class ManagerTest { 
    @InjectMocks 
    Manager manager = new Manager(); 

    @Mock 
    SomeUrl mockUrl; // <- This is the mock that will be injected by Mockito 

    @Test 
    public void testMethod(){ 
     // Given 
     when(mockUrl.getUrlString()).thenReturn("SomeUrl"); 

     // When 
     manager.method(); 

     // Then 
     verify(mockUrl, times(1)).getUrlString(); 
    } 
} 
+0

ОК. спасибо. url - это просто String, и когда я отлаживаю код, реальный SomeService.get() выглядит как возвращающий String не null. Спасибо за ваше решение. Мне нравится знать, хорошо ли создавать «SomeUrl»? – c2340878

+0

прочитайте некоторые модульные тесты и введение в Mockito, и поймите, зачем нам насмехаться/стучать. Основная идея состоит в том, чтобы протестировать против SUT и избежать поведения зависимостей от влияния на тесты. С помощью stubbing вы можете управлять зависимостями, чтобы вести себя так, как вам нужно для конкретного теста. –

-2

да, все правильно. Поскольку Mock является динамическим прокси, а url - статическая переменная, определенная в классе. В основном макет используется для издевательства ожидаемого поведения (метода), поэтому, если вы хотите вернуть какой-то URL-адрес, который вам нравится, вы можете использовать, когда метод getUrl возвращает URL-адрес, который вам нравится. В вашем сценарии вы можете вернуть SomeService.get()

+0

Проблема здесь не связана с динамическим прокси-фактом mock. Просто не насмехается. 'InjectMocks' не создает прокси для SUT. –

Смежные вопросы