Powermock содержит () не работает

Я пытаюсь смоделировать HTTP-вызов с помощью PowerMockito, но у меня возникли некоторые проблемы с contains() функция. Мой план состоит в том, чтобы проверить, содержит ли путь определенную строку, а затем я возвращаю фиктивный объект. Итак, у меня есть следующая функция:

import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*;
import static org.mockito.Matchers.*;
import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.powermock.api.mockito.PowerMockito.*;
private static <T> void mockResponse(Class<T> type, T response, String pathContains) throws Exception
{
    mockStatic(ClientBuilder.class);
    Client client = mock(Client.class);
    when(ClientBuilder.class, "newClient").thenReturn(client);
    WebTarget webTarget = mock(WebTarget.class);
    when(client.target(anyString())).thenReturn(webTarget);

    //This is what doesn't work
    when(webTarget.path(contains(pathContains))).thenReturn(webTarget);

    when(webTarget.queryParam(any(), any())).thenReturn(webTarget);
    Invocation.Builder invocationBuilder = mock(Invocation.Builder.class);
    when(webTarget.request()).thenReturn(invocationBuilder);
    Invocation invocation = mock(Invocation.class);
    when(invocationBuilder.buildGet()).thenReturn(invocation);

    Response res = mock(Response.class);
    when(invocation.invoke()).thenReturn(res);
    when(res.readEntity(type)).thenReturn(response);
}

mockResponse(GenreList.class, new GenreList(new Genre(0, "g")), "genre");

Проблема в том, что я получаю нулевой указатель при попытке сделать HTTP-вызов:

    Response res = client.target(theMovieDbURL)
                         .path("/3/genre/movie/list")
                         .queryParam("api_key", apiKey)
                         .request()
                         .buildGet()
                         .invoke();

Если я, где изменить макет из contains() в anyString() это работает как шарм, но мне нужно иметь разные ответы для разных путей, поэтому я не могу оставить это как anyString(), Я пытался изменить его на eq() также, но это тоже не работает.

Что мне здесь не хватает?

из моего gradle:

testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.6.6'
testCompile group: 'org.powermock', name: 'powermock-api-mockito', version: '1.6.6'
testCompile group: 'org.powermock', name: 'powermock-module-junit4-rule', version: '1.6.6'

1 ответ

Больше без ответа: вы идете по неправильной кроличьей норе здесь.

Дело в том, что цель теста - убедиться, что конкретный производственный код реализует то требование, которое должен охватывать тест. Ничего больше.

Приводит к тому, что вы предпочитаете несколько простых, простых тестов, а не один кусок кода, способный обрабатывать множество различных аспектов.

Значение: вы не идете и не начинаете использовать

when(webTarget.path(contains(pathContains))).thenReturn(webTarget);

где у вас есть различные возможности, которые может содержать содержащаяся (). Вместо этого у вас есть n тестов, которые явно говорят

when(webTarget.path(contains(A))).thenReturn(webTargetA);

...

when(webTarget.path(contains(B))).thenReturn(webTargetB);

Другими словами: вы намереваетесь как-то выразить умную "бизнес-логику" в своем тестовом коде. Вы хотите сделать это "умным". Не делай этого. Вместо этого сосредоточьтесь на написании тестового кода, который, как уже говорилось, прямо создает конкретную настройку, а затем тестирует одну вещь.

Другими словами: в вашем тестовом коде не должно быть необходимости указывать конкретные возвращаемые значения. Потому что вы определяете настройки (и, следовательно, пути), которые увидит ваш производственный код. Вы говорите, что выбираете путь A для одного теста, а путь B в другом тесте. И тогда ваше желание разработать, если / то логика исчезает в воздухе.

Другие вопросы по тегам