2015-03-31 4 views
9

Вы знаете, как правильно издеваться над Elasticearch Java Client? В настоящее время, чтобы издеваться следующий запрос в Java:Как насмехаться с Elasticearch Java Client?

SearchResponse response = client.prepareSearch(index) 
       .setTypes(type) 
       .setFrom(0).setSize(MAX_SIZE) 
       .execute() 
       .actionGet(); 
SearchHit[] hits = response.getHits().getHits(); 

я должен издеваться:

  • client.prepareSearch
  • SearchRequestBuilder:
    • builder.execute
    • builder.setSize
    • builder.setF
    • builder.setTypes
  • SearchResponse:
    • action.actionGet
  • SearchResponse:
    • response.getHits
    • searchHits.getHits

Так что мой тест выглядит следующим образом:

SearchHit[] hits = ..........; 

SearchHits searchHits = mock(SearchHits.class); 
when(searchHits.getHits()).thenReturn(hits); 

SearchResponse response = mock(SearchResponse.class); 
when(response.getHits()).thenReturn(searchHits); 

ListenableActionFuture<SearchResponse> action = mock(ListenableActionFuture.class); 
when(action.actionGet()).thenReturn(response); 

SearchRequestBuilder builder = mock(SearchRequestBuilder.class); 
when(builder.setTypes(anyString())).thenReturn(builder); 
when(builder.setFrom(anyInt())).thenReturn(builder); 
when(builder.setSize(anyInt())).thenReturn(builder); 
when(builder.execute()).thenReturn(action); 

when(client.prepareSearch(index)).thenReturn(builder); 

Гадкий ... Так что я хотел бы известно, если есть более «элегантный способ» издеваться этот код.

Благодаря

+1

Для чего это стоит, я думаю, что вы собираетесь слишком низкоуровневым. Вы должны только тестировать ** свой ** код, а не проверять, работает ли Elasticsearch: предположите, что это так. Поэтому я предполагаю, что у вас есть метод, который обертывает весь этот код: например. 'public String [] search (searchParams ..) {SearchResponse response = client.prepareSearch (index) .. и т. д .; SearchHit [] hits = response.getHits(). GetHits(); обратные хиты; } '. Ваш тест должен высмеять ваш метод 'search' и вернуть mock' String [] 'результаты для разных входов. –

ответ

2

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

Как сказал г-н Лоун, возможно, лучше, если вы можете избежать этого, в первую очередь, поскольку это не ваш код, и его можно считать «просто работающим», но я думал, что дам ему пойти в любом случае ,

Я придумал (возможно, грубый) способ сделать это, используя «ответы по умолчанию» в Mockito. Я все еще решаю, нравится мне это или нет.

Вот мой строитель ...

public class MyBuilder { 

    private StringBuilder my; 

    public MyBuilder() { 
     my = new StringBuilder(); 
    } 

    public MyBuilder name(String name) { 
     my.append("[name=").append(name).append("]"); 
     return this; 
    } 

    public MyBuilder age(String age) { 
     my.append("[age=").append(age).append("]"); 
     return this; 
    } 

    public String create() { 
     return my.toString(); 
    } 
} 

(Довольно основных прав?)

Я получил мой тест, чтобы посмотреть что-то вроде этого ...

// Create a "BuilderMocker" (any better name suggestions welcome!) 
    BuilderMocker<MyBuilder> mocker = BuilderMocker.forClass(MyBuilder.class); 
    // Get the actual mock builder 
    MyBuilder builder = mocker.build(); 

    // expect this chain of method calls... 
    mocker.expect().name("[NAME]").age("[AGE]"); 

    // expect this end-of-chain method call... 
    Mockito.when(builder.create()).thenReturn("[ARGH!]"); 

Теперь, если я следующие ...

System.out.println(builder.name("[NAME]").age("[AGE]").create()); 

... Я ожидаю, что «[ARGH!]» Будет выводиться.

Если я изменил последнюю строку ...

System.out.println(builder.name("[NOT THIS NAME]").age("[AGE]").create()); 

... тогда я ожидаю, что он сломается с помощью NullPointerException.

Вот собственно «BuilderMocker» ...

import static org.mockito.Mockito.mock; 
import static org.mockito.Mockito.when; 
import static org.mockito.Mockito.withSettings; 

import org.mockito.invocation.InvocationOnMock; 
import org.mockito.stubbing.Answer; 

public class BuilderMocker<T> { 

    private Class<T> clazz; 
    private T recorder; 
    private T mock; 

    // Create a BuilderMocker for the class 
    public static <T> BuilderMocker<T> forClass(Class<T> clazz) { 
     return new BuilderMocker<T>(clazz); 
    } 

    private BuilderMocker(Class<T> clazz) { 
     this.clazz = clazz; 
     this.mock = mock(clazz); 
     createRecorder(); 
    } 

    // Sets up the "recorder" 
    private void createRecorder() { 
     recorder = mock(clazz, withSettings().defaultAnswer(new Answer<Object>() { 

      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       // If it is a chained method... 
       if (invocation.getMethod().getReturnType().equals(clazz)) { 
        // Set expectation on the "real" mock... 
        when(invocation.getMethod().invoke(mock, invocation.getArguments())).thenReturn(mock); 
        return recorder; 
       } 
       return null; 
      } 

     })); 
    } 

    // Use this to "record" the expected method chain 
    public T expect() { 
     return recorder; 
    } 

    // Use this to get the "real" mock... 
    public T build() { 
     return mock; 
    } 
} 

Не уверен, что если есть «встроенный» способ сделать это в Mockito, но это, кажется, работает.

+0

Мне нравится этот подход. Я должен разработать своих строителей в качестве библиотеки и повторно использовать эти классы в ходе моих тестов. Спасибо! –

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