Захватить аргумент в Мокито - PullRequest
6 голосов
/ 01 сентября 2010

Я тестирую определенный класс. Этот класс внутренне создает экземпляр объекта "GetMethod", который передается объекту "HttpClient", который вводится в тестируемый класс.

Я издеваюсь над классом "HttpClient", но мне также нужно изменить поведение одного метода класса "GetMethod". Я играю с ArgumentCaptor, но мне кажется, что я не могу удержать экземпляр объекта в вызове «когда».

Пример:

HttpClient mockHttpClient = mock(HttpClient.class);
ArgumentCaptor<GetMethod> getMethod = ArgumentCaptor.forClass(GetMethod.class);
when(mockHttpClient.executeMethod(getMethod.capture())).thenReturn(HttpStatus.SC_OK);
when(getMethod.getValue().getResponseBodyAsStream()).thenReturn(new FileInputStream(source));

Ответ:

org.mockito.exceptions.base.MockitoException: 
No argument value was captured!
You might have forgotten to use argument.capture() in verify()...
...or you used capture() in stubbing but stubbed method was not called.
Be aware that it is recommended to use capture() only with verify()

Ответы [ 2 ]

12 голосов
/ 02 сентября 2010

Вы не можете использовать when на getMethod, потому что getMethod - это не фальшивка. Это все еще реальный объект, созданный вашим классом.

ArgumentCaptor имеет совершенно другое назначение. Проверьте раздел 15 здесь .

Вы можете сделать свой код более тестируемым. Как правило, классы, создающие новые экземпляры других классов, сложно протестировать. Поместите некоторую фабрику в этот класс для создания методов get / post, затем в тесте смоделируйте эту фабрику и сделайте так, чтобы она имитировала методы get / post.

public class YourClass {
  MethodFactory mf;

  public YourClass(MethodFactory mf) {
    this.mf = mf;
  }

  public void handleHttpClient(HttpClient httpClient) {
    httpClient.executeMethod(mf.createMethod());
    //your code here
  }
}

Тогда в тесте вы можете сделать:

HttpClient mockHttpClient = mock(HttpClient.class);
when(mockHttpClient.executeMethod(any(GetMethod.class)).thenReturn(HttpStatus.SC_OK);

MethodFactory factory = mock(MethodFactory.class);
GetMethod get = mock(GetMethod.class);
when(factory.createMethod()).thenReturn(get);
when(get.getResponseBodyAsStream()).thenReturn(new FileInputStream(source));

ОБНОВЛЕНИЕ

Вы также можете попробовать какой-нибудь мерзкий взлом, и Answer и получить доступ к закрытым частям GetMethod;) по рефлексии. (Это действительно противный хак)

when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new Answer() {
  Object answer(InvocationOnMock invocation) {
    GetMethod getMethod = (GetMethod) invocation.getArguments()[0];

    Field respStream = HttpMethodBase.class.getDeclaredField("responseStream");
    respStream.setAccessible(true);
    respStream.set(getMethod, new FileInputStream(source));

    return HttpStatus.SC_OK;
  }
});
4 голосов
/ 02 сентября 2010

Хорошо, вот как я это решил.Немного запутанный, но не смог найти другого пути.

В тестовом классе:

private GetMethod getMethod;

public void testMethod() {
    when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new ExecuteMethodAnswer());
    //Execute your tested method here.
    //Acces the getMethod here, assert stuff against it.  
}

private void setResponseStream(HttpMethodBase httpMethod, InputStream inputStream) throws NoSuchFieldException, IllegalAccessException {
    Field privateResponseStream = HttpMethodBase.class.getDeclaredField("responseStream");
    privateResponseStream.setAccessible(true);
    privateResponseStream.set(httpMethod, inputStream);
}

private class ExecuteMethodAnswer implements Answer {
    public Object answer(InvocationOnMock invocation) throws FileNotFoundException,
                                                             NoSuchFieldException, IllegalAccessException {
        getMethod = (GetMethod) invocation.getArguments()[0];
        setResponseStream(getMethod, new FileInputStream(source));
        return HttpStatus.SC_OK;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...