2016-01-10 4 views
1

У меня есть 2 класса взаимодействия. Say ServiceLayer.class и ApiAdaptor.class:как частично издеваться над внешним вызовом метода с использованием powermock

public class ApiAdaptor { 
    public String getCountry(String latitude, String longitude) { 
    // REST call to api goes here and a the country string is returned 
    return country; 
    } 
} 

public class ServiceLayer { 
public String findCountry(int positionId) { 
    // some business logic here to get latitude and longitude from postitionId 
    ApiAdaptor api = new ApiAdaptor(); 
    String country = api.getCountry(latitude, longitude); 
    return country; 
} 
} 

Сейчас в тестовом модуле, я хочу проверить только этот метод ServiceLayer.findcountry(), а насмешливый внутренний вызов ApiAdaptor.getCountry(latitude, longitude). Есть ли способ, которым я могу это сделать, используя Powermock. Я видел подобный тип заглушки во время работы с Rspec в Ruby On Rails. Я хочу сделать подобное тестирование и в моем проекте java-SpringMVC.

ответ

1

Конечно, вы можете использовать PowerMock для фокусировки только на этом методе. Например, с помощью PowerMockito конкретно, вы можете написать этот тест:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ServiceLayer.class}) 
public class PowerMockitoJan10Test { 
    private static final java.lang.String DESIRED_COUNTRY_VALUE = "USA"; 

    @Test 
    public void testServiceLayerFindCountry() throws Exception { 
     ApiAdaptor mock = Mockito.mock(ApiAdaptor.class); 
     PowerMockito.whenNew(ApiAdaptor.class).withAnyArguments().thenReturn(mock); 
     Mockito.when(mock.getCountry(Mockito.anyString(), Mockito.anyString())).thenReturn(DESIRED_COUNTRY_VALUE); 

     String country = new ServiceLayer().findCountry(1); 
     Assert.assertEquals(DESIRED_COUNTRY_VALUE, country); 
    } 
} 

Если вы используете Spring, то, скорее всего, что вам нужно JUnit бегуна для этого тоже, так что вы можете использовать правило JUnit для PowerMockito вместо - see this example ,


Редактировать: это интересно. При использовании правила это не работает, если вы не добавите ServiceLayer.class в список @PrepareForTest. Я использовал последнюю версию PowerMockito на момент написания этой статьи, 1.6.4. Может быть, стоит сообщить. В любом случае, это то, как ваш тест будет работать с Spring:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("mycontext.xml") 
@PrepareForTest({ApiAdaptor.class, ServiceLayer.class}) 
public class PowerMockitoJan10_WithRuleTest { 
    private static final String DESIRED_COUNTRY_VALUE = "USA"; 

    @Rule 
    public PowerMockRule rule = new PowerMockRule(); 

    @Test 
    public void testServiceLayerFindCountry() throws Exception { 
     PowerMockito.whenNew(ApiAdaptor.class).withNoArguments().thenReturn(new ApiAdaptor() { 
      @Override 
      public String getCountry(String latitude, String longitude) { 
       return DESIRED_COUNTRY_VALUE; 
      } 
     }); 

     String country = new ServiceLayer().findCountry(1); 
     Assert.assertEquals(DESIRED_COUNTRY_VALUE, country); 
    } 

} 

Или, если переопределение является проблемой, вы можете издеваться ApiAdaptor:

... 
    ApiAdaptor mock = PowerMockito.mock(ApiAdaptor.class); 
    PowerMockito.when(mock.getCountry(Mockito.anyString(), Mockito.anyString())).thenReturn(DESIRED_COUNTRY_VALUE); 
    PowerMockito.whenNew(ApiAdaptor.class).withNoArguments().thenReturn(mock); 
    ... 
+0

Я делаю то же самое, но когда я запускаю тест, зашитый метод не вызывается, и законченный метод запускается ... :( – ishanbakshi

+0

моя конфигурация аннотации выглядит примерно так: @RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration @PrepareForTes t ({ServiceLayer.class}) – ishanbakshi

+0

Вы были правы, это не работает так, как при переключении на правило. Но я добавил «ServiceLayer.class» в список в аннотации, и теперь он работает хорошо. –

0

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

Вы бы что-то вроде этого:

public class ServiceLayer { 
    private ApiAdaptor _api; 
    public ServiceLayer(ApiAdaptor api) { 
     _api = api; 
    } 
    [snip] 
} 

Затем использовать _api в остальной части кода.

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

ApiAdaptor mock = Mockito.mock(ApiAdaptor.class); 
[Api adaptor behavior mocking] 
String country = new ServiceLayer(mock).findCountry(1); 
[asserts and all] 

Это устраняет необходимость в PowerMockito, салазок и/или правил ...

+0

Thnks для предложений ... В настоящее время я делаю инъекцию зависимостей , но я чувствую, что в какой-то момент в будущем мне придется использовать power mock, потому что я не могу продолжать объявлять переменные класса ... Вот почему я ищу решение, специфичное для power mock или аналогичной библиотеки. – ishanbakshi

+0

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

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