как издеваться над звонками клиентов ВС Джерси? - PullRequest
0 голосов
/ 10 февраля 2019

Это мой код

@Service
public class PaymentHandler {
private static final Gson GSON = new Gson();

private static Client webServiceClient = createSslClient(); // function creates a ssl connection

public Response makePayment(String payload) {
    WebResource webResource = webServiceClient.resource(url);

    WebResource.Builder builder = webResource.getRequestBuilder();

    String r = builder
            .type(MediaType.APPLICATION_JSON_TYPE)
            .accept(MediaType.APPLICATION_JSON_TYPE)
            .post(String.class, payload);

    Response response = GSON.fromJson(r, Response.class);
}
}

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

Client client = mock(Client.class );
WebResource webResource = mock(WebResource.class);
WebResource.Builder builder = mock(WebResource.Builder.class);
ClientResponse clientResponse = mock(ClientResponse.class);
when(client.resource(anyString())).thenReturn(webResource);
when(webResource.getRequestBuilder()).thenReturn(builder);

when(builder.type(anyString())).thenReturn(builder);
when(builder.accept(anyString())).thenReturn(builder);
when(builder.post(Matchers.eq(String.class), anyString())).thenReturn("Test");
paymentHandler.makePayment(payload); //assume that I send actual payload

Может кто-нибудь сказать, пожалуйста, как это издеваться?

Ответы [ 2 ]

0 голосов
/ 17 марта 2019

Вот как я это использовал:

@Mock
Client client;

@Mock
WebResource webResource;

@Mock
WebResource.Builder builder;


@Test
public void test() {
ReflectionTestUtils.setField(payeezyHandler,"webServiceClient",client);
Mockito.when(client.resource(anyString())).thenReturn(webResource);
Mockito.when(webResource.getRequestBuilder()).thenReturn(builder);

Mockito.when(builder.type(MediaType.APPLICATION_JSON_TYPE)).thenReturn(builder);
Mockito.when(builder.accept(MediaType.APPLICATION_JSON_TYPE)).thenReturn(builder);
Mockito.when(builder.post(Matchers.eq(String.class),anyString())).thenReturn(fakeResponse());
}

Я знаю, что ReflectionTestUtils плохо использовать.Но если в вашем тестовом классе есть только одна открытая функция для тестирования, то, я думаю, это не повредит.

0 голосов
/ 10 февраля 2019

В вашем тесте я не вижу, чтобы вы заменили webServiceClient на смоделированную версию.

Но, во-первых, я считаю, что вам лучше не писать такой код как PaymentHandler без внедрения зависимостей.Это может быть просто простая композиция с webServiceClient, вводимым в PaymentHandler.Без внедрения зависимостей он не гибкий, трудно обслуживаемый и, как следствие, не тестируемый.Представьте, например, что произойдет, если для инициализации такого поля потребуется некоторое взаимодействие с внешней системой.Как бы вы протестировали его без каких-либо библиотек, манипулирующих байт-кодом?Или как бы вы могли легко перейти с одного webServiceClient на другой, например, с не-ssl на ssl?

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

@RunWith(PowerMockRunner.class)
@PrepareForTest(PaymentHandler.class)
public class PaymentHandlerTest {
    @Test
    public void test() throws Exception {
        //we don't want to initialize the PaymentHandler.class because it might cause some
        //heavy undesirable initilization. E.g. if we had referred to PaymentHandler as a class
        //literal here, then the webServiceClient would've been initializaed with some "real"
        //instance of Client. My PaymentHandler is located in so package. You should specify your
        //fully qualified class' name here
        Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("so.PaymentHandler");

        //now the webServiceClient will be null once we initialize the PaymentHandler class
        PowerMockito.suppress(PowerMockito.method(clazz, "createSslClient"));
        Client client = mock(Client.class);

        //here we initialize the PaymentHandler.class and finally mock the webServiceClient
        Whitebox.setInternalState(clazz, "webServiceClient", client);

        PaymentHandler paymentHandler = new PaymentHandler();

        WebResource webResource = mock(WebResource.class);
        WebResource.Builder builder = mock(WebResource.Builder.class);
        when(client.resource(anyString())).thenReturn(webResource);
        when(webResource.getRequestBuilder()).thenReturn(builder);
        //take note of any(MediaType.class) instead of anyString() from your example. As in
        //your PaymentHandler, MediaType is used instead of String
        when(builder.type(any(MediaType.class))).thenReturn(builder);
        when(builder.accept(any(MediaType.class))).thenReturn(builder);
        when(builder.post(Matchers.eq(String.class), anyString())).thenReturn("{}");

        paymentHandler.makePayment("payload");
    }
}

В моем примере я использовал следующие зависимости:

testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.0'
testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0'

Это последние версии, но ранееверсии могут сделать это также

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