Depuis le service, j'appelle l'API tierce en utilisant RestTemplate.
@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()); }
J'ai essayé d'utiliser à la fois la méthode any () et de spécifier directement les valeurs. Spécifier directement la valeur dans entity ne semble pas être la bonne façon de tester. Voici la classe de service pour laquelle j'ai besoin d'écrire des cas de test.
@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); } }
Le cas de test ci-dessus renvoie l'échange ResponseEntity comme nul. Existe-t-il une solution pour que le scénario de test fonctionne pour l'appel d'échange RestTemplate?
3 Réponses :
Vous devez dire à Mockito ce qu'il doit renvoyer lorsque le simulacre est appelé ...
when(restTemplate.exchange(anyString(), any(), any(), any())).thenReturn(...
Insérez l'entité de réponse que vous voulez renvoyer de l'appel à échanger dans le thenReturn.
J'ai créé la réponse et j'ai réussi aussi, mais cela n'a pas fonctionné. En outre, ResponseEntity
Pouvez-vous mettre à jour le code de votre message avec la modification et l'erreur que vous obtenez?
La vérification doit aller après l'appel au code de production, dans votre cas l'appel createLead ()
. Vous allez également vouloir utiliser des matchers pour votre appel, qui ne devraient probablement pas être commentés. Dans des cas comme le vôtre, vous n'avez généralement pas besoin à la fois du moment et de la vérification. Cela rend simplement le test plus complexe et plus difficile à lire.
J'utilise la vérification s'il n'y a pas de retour de l'appel de service sur lequel je peux affirmer. Dans ces cas, j'emballerais tous les paramètres du when (si nécessaire pour dépasser une exception de pointeur nul ou une autre erreur) dans any () tel que any (HttpEntity.class)
ou anyString ()
donc les paramètres ne sont pas ambigus. Ensuite, vous pouvez utiliser la vérification pour confirmer que les paramètres réels sont corrects. Cette stratégie est plus facile à maintenir. Malheureusement, il faut souvent un capteur d'arguments pour vérifier que les en-têtes ou autres paramètres sont envoyés correctement. Je dis que c'est malheureux parce que les tests deviennent gros et compliqués,
Si je peux affirmer sur le résultat, j'utilise souvent juste le quand. Dans ce cas, j'envelopperais les paramètres avec eq ()
, comme eq (httpEntity)
. Dans ce cas, la classe HttpEntity aurait besoin d'une bonne méthode .equals ()
ou elle utiliserait simplement la valeur par défaut et n'est probablement pas très utile. Mais, il est généralement assez puissant.
Vous ne devez pas utiliser @InjectMocks
et initialiser dans la configuration. Si vous @InjectMocks
, il crée l'instance et injecte les simulacres. Vous semblez vouloir mettre une vraie configuration afin que vous utilisiez la méthode de configuration ou vous pourriez vous moquer de la configuration. J'ai utilisé un matcher correct, mais vous devrez peut-être les affiner, par exemple changer certains any ()
en eq ()
pour vraiment tester ce que vous voulez tester. J'ai également réorganisé pour que l'action ou l'appel à la production soit avant la vérification. Ce test devrait vous aider à démarrer.
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)); } }
Mockito.when (restTemplate.exchange (Matchers.eq (url), Matchers.eq (HttpMethod.POST), Matchers.
@Sowmeashree a écrit un exemple qui utilise votre code.
Le code @DCTID m'a sauvé la journée. Parallèlement à cela, j'ai rencontré le problème ci-dessous et je l'ai résolu. Pour se moquer du corps de ResponseEntity, j'ai créé un objet et lui ai défini une valeur. Sinon, il ne passait pas cette condition - 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));