2014-09-16 4 views
0

я следующие настройки:JMockit - Передразнивал метода, возвращающих интерфейсы

public String loadFile(String uri) throws ClientProtocolException, IOException { 
     StringBuilder resp = new StringBuilder(); 
     HttpClient client = HttpClientBuilder.create().build(); 
     HttpGet request = new HttpGet(uri); 
     HttpResponse response = client.execute(request); 
} 

с TestClass глядя, как это:

@RunWith(JMockit.class) 
public class FakeLoaderTest { 

    FakeLoader loader = new FakeLoader(); //class under test 

    @Test 
    public void testLoadFile( 
     @Mocked @Cascading final HttpClientBuilder mockBuilder, 
     @Capturing final HttpClient mockClient 
    ) throws IOException, URISyntaxException{ 

     new Expectations() {{ 
      HttpClientBuilder.create().build(); result = mockClient; 
      mockClient.execute(withAny(mockget)); result = new IOException("test - test"); 
     }}; 

     loader.loadFile(); 
    } 
} 

это дает мне «Неожиданное призывание ClosableHttpClient.execute - ожидаемая была HttpClient .execute "

HttpClientBuilder.create.build() возвращает ClosableHttpClient, который реализует HttpClient. Я думал, что @Capturing позаботился о Mocking для всех классов, расширяющих рассматриваемый класс/интерфейс?

Это прекрасно работает, как ожидалось:

@Mocked @Cascading final HttpClientBuilder mockBuilder, 
    @Capturing final **Closeable**HttpClient mockClient 

Но я хочу, чтобы проверить против интерфейса, потому что я не пробное применение HttpClient, который используется. В этом тесте мне неинтересно, если кто-то из apache решает, что ClosableHttpClient сменил «ThinHttpCLient» как реализацию по умолчанию, если apache придерживается интерфейса HttpClient, я не хочу изменять этот тестовый файл. Речь идет о проверке внутренней обработки исключения IO (например, он находится в правильном месте? Правильно ли он повторяет и т. Д.)

Как справиться с этим с помощью JMockit и JUnit?

спасибо заранее,

BillDoor

ответ

0

Испытание должно быть следующим:

@Test(expected = IOException.class) 
public void loadFile(
    @Cascading HttpClientBuilder mockBuilder, 
    @Mocked final CloseableHttpClient mockClient 
) throws Exception 
{ 
    new NonStrictExpectations() {{ 
     mockClient.execute((HttpGet) any); result = new IOException("test"); 
    }}; 

    loader.loadFile("uri"); 
} 

Тип возврата HttpClientBuilder#build()являетсяCloseableHttpClient, который является абстрактным классом, содержащий общие реализации метода , Проект Apache никогда не сможет изменить этот тип возврата на что-то еще, потому что это будет нарушение API-интерфейса, что приведет к ошибкам компиляции.

Кроме того, @Capturing не делает ничего более того, что @Mocked в этом случае, поскольку использование @Cascading HttpClientBuilder подразумевает, что не будет создан экземпляр реального класса реализации.

+0

@Cascading (ii получил это право) означает, что объекты, возвращенные прикованным вызовом, тоже будут издеваться, поэтому я поместил его для build(). Create(), но, обратив внимание на то, что это не необходимо. Что касается CloseableHttpClient beeing unchangable API, я помню использование таких вещей, как «new DefaultHttpClient()», который теперь устарел и изменился на HttpClientBuilder(). Build(). Create() beeing используется. Если apache предоставляет интерфейс, я бы хотел использовать его, если это возможно. Вы говорите, что вы уверены, что это невозможно? - если это так, просто подтвердите, и я приму ответ – billdoor

+0

@billdoor 'DefaultHttpClient' расширяет' CloseableHttpClient', который фактически является истинным базовым типом для библиотеки. Я не знаю точно, зачем нужен интерфейс Java, но я бы сказал, что, вероятно, «HttpClient» должен был быть абстрактным классом, который является «CloseableHttpClient». Итак, да, я был бы очень удивлен, если бы они когда-либо заставили метод 'build()' возвращать что-нибудь еще. –

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