Как написать тестовые примеры Mockito Junit для шаблона Rest? - PullRequest
0 голосов
/ 28 января 2019

Из службы я вызываю сторонний API с помощью RestTemplate.

@RunWith(MockitoJUnitRunner.class)
public class ForceServiceTest {
@InjectMocks
private ForceService forceService;
@Mock
private RestTemplate restTemplate;
@Before
public void setup() {
    forceService = new ForceService(config, restTemplate);
}
@Test
public void createTest_valid() throws JSONException {
    /*Mockito.when(restTemplate.exchange(url, HttpMethod.POST, entity, CreateRecordResult.class))
    .thenReturn(response);*/
     Mockito.verify(restTemplate, Mockito.times(1))
    .exchange(Mockito.anyString(),
                    Mockito.<HttpMethod> any(),
                    Mockito.<HttpEntity<?>> any(),
                    Mockito.<Class<?>> any());
    forceService.createLead(lead);
}
}

Я пытался использовать метод any () и напрямую указывать значения.Непосредственное указание значения в сущности не является правильным способом проверки.Ниже приведен класс обслуживания, для которого мне нужно написать контрольные примеры.

@Component
public class ForceService {
    private RestTemplate restTemplate;
public ForceService(ForceServiceConfig config,  RestTemplate restTemplate) {
    this.config = config;
    this.restTemplate = restTemplate;
}
public String createLead(Lead lead) {
    HttpHeaders headers = new HttpHeaders();
    headers.set(AUTHORIZATION, getAccessToken());
    headers.set(ACCEPT, APPLICATION_JSON);
    headers.set(CONTENT_TYPE, APPLICATION_JSON);
    LeadWrap leadWrap = new LeadWrap();
    leadWrap.setFirstName(lead.getFirstName());
    leadWrap.setLastName(lead.getLastName());
    leadWrap.setEmail(lead.getEmail());
    leadWrap.setPhone(lead.getPhone());

    String jsonString;
    try {
        jsonString = new ObjectMapper().writeValueAsString(leadWrap);

    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    HttpEntity<String> entity = new HttpEntity<>(jsonString, headers);

    ResponseEntity<CreateRecordResult> exchange = restTemplate.exchange(
            config.restUrl + "/v" + config.restVersion + "/sobjects/Lead/", HttpMethod.POST, entity,
            CreateRecordResult.class);
    if (exchange.getStatusCode().equals(HttpStatus.CREATED)) {
        if (exchange.getBody() != null && exchange.getBody().success) {
            LOGGER.info("Lead record created with Id " + exchange.getBody().id);
            return exchange.getBody().id;
        }
        throw new RuntimeException("Record is not created");
    } else {
        LOGGER.error(RETURN_STATUS + exchange.getStatusCode());
        throw new RuntimeException(RETURN_STATUS + exchange.getStatusCode());
    }

Приведенный выше контрольный пример возвращает обмен ResponseEntity как ноль.Есть ли какое-нибудь решение для этого, чтобы заставить контрольный пример работать для вызова обмена RestTemplate?

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Проверка должна идти после вызова производственного кода, в вашем случае вызов createLead().Вы также захотите использовать совпадения для вашего когда звоните, что, вероятно, не следует закомментировать.В таких случаях, как ваш, вам, как правило, не нужны ни когда, ни проверка.Это только делает тест более сложным и трудным для чтения.

Я использую проверку, если нет возврата от сервисного вызова, на котором я могу утверждать.В этих случаях я бы обернул все параметры оператора when (если необходимо обойти исключение нулевого указателя или другую ошибку) в any (), например, any(HttpEntity.class) или anyString(), чтобы параметры не были неоднозначными.Затем вы можете использовать команду проверки для подтверждения того, что фактические параметры верны.Эту стратегию легче поддерживать.К сожалению, часто требуется захватчик аргументов для проверки правильности отправки заголовков или других параметров.Я говорю, что это неудачно, потому что тесты становятся большими и грязными,

Если я могу утверждать результат, я часто просто использую когда.В этом случае я бы обернул параметры с eq(), например eq(httpEntity).В этом случае класс HttpEntity должен иметь хороший метод .equals(), или он будет просто использовать значение по умолчанию и, вероятно, не очень полезен.Но, как правило, это довольно мощный.

Вы не должны использовать @InjectMocks и инициализировать в настройках.Если вы @InjectMocks он создает экземпляр и внедряет макеты.Вы, кажется, хотите поставить реальный конфиг, чтобы использовать метод настройки или смоделировать конфиг.Я использовал правильное сопоставление, но вам, возможно, придется его уточнить, например, переключите any() на eq(), чтобы действительно проверить то, что вы хотите проверить.Я также изменил порядок, так что действие или вызов производственного вызова перед проверкой.Этот тест должен помочь вам начать.

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class ForceServiceTest {

    private ForceService forceService;
    @Mock
    private RestTemplate restTemplate;

    @Before
    public void setup() {
        forceService = new ForceService(new ForceServiceConfig(), restTemplate);
    }

    @Test
    public void createTest_valid() throws Exception {
        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST),
                any(HttpEntity.class),
                eq(CreateRecordResult.class)))
                .thenReturn(new ResponseEntity<>(new CreateRecordResult(), HttpStatus.CREATED));

        forceService.createLead();

        verify(restTemplate, times(1))
                .exchange(eq("config.restUrl/vconfig.restVersion/sobjects/Lead/"),
                        any(HttpMethod.class),
                        any(HttpEntity.class),
                        eq(CreateRecordResult.class));
    }
}
0 голосов
/ 30 января 2019

@ Код DCTID спас мой день.Вместе с тем я столкнулся с проблемой ниже и исправил ее.Чтобы высмеивать тело ResponseEntity, я создал объект и установил для него значение.Иначе, это условие не проходило - if (exchange.getBody ()! = Null && exchange.getBody (). Success)

CreateRecordResult createRecordResult = new CreateRecordResult();
createRecordResult.success = true;
Mockito.when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class),
            eq(CreateRecordResult.class)))
                    .thenReturn(new ResponseEntity<>(createRecordResult, HttpStatus.CREATED));
0 голосов
/ 28 января 2019

Вы должны указать Mockito, что возвращать при вызове mock ...

when(restTemplate.exchange(anyString(), any(), any(), any())).thenReturn(...

Вставить responseEntity, который вы хотите вернуть от вызова к обмену, в thenReturn.

...