Как мне смаковать метод getForEntity () Rest Template - PullRequest
1 голос
/ 04 июля 2019

Я новичок в mockito и мне нужна помощь, возможно, пример того, как смоделировать методы Rest Template getForEntity и postForEntity. Ниже приведен код, для которого я хочу написать контрольные примеры Junit, высмеивая метод getForEntity.

SomeService.java

class SomeService
{
   //some private, static,  final data members
   public Map getService(String sNo, String uId, String en)
   {
      ResponseEntity <Map> response = new 
      RestTemplate().getForEntity("https://someurl.com/someService", 
      Map.class);
      Map body = response.getBody();
      //do something

      HttpEntity<?> request = new HttpEntity <>(payLoad, headers);
      //payload is Hash Map and headers is a LinkedMultiValueMap
      ResponseEntity <Map> response = new RestTemplate().postForEntity(url, 
      request, headers);
      return response.getBody(); 

   }   
}

Я пытался что-то сделать с @Mock и @InjectMocks.

TestSomeService.java

@RunWith(MockitoJunitRunner.class)
class TestSomeService
{
   @Mock
   RestTemplate restTemplate;
   @InjectMocks
   SomeService ser;
   /*Some data members*/
   @Before
   {
      HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);
      Mockito.when(restTemplate.getForEntity("theUrl", 
      Map.class)).thenReturn(new ResponseEntity <Map>(someMap, 
      HttpStatus.OK));
      Mockito.when(restTemplate.postForEntity("anotherUrl", request, 
      Map.class)).thenReturn(new ResponseEntity <Map>(expectedMap, 
      HttpStatus.OK));

   }  
   @Test
   public void testGetService()
   {
       Map <String, Object> result = ser.getService("123", "abc", "QA");
   }    
}

Ответы [ 5 ]

1 голос
/ 04 июля 2019

Когда вы вызываете конкретное значение, вы должны заключить его в ArgumentMatchers.eq().Однако вы можете использовать anyString(), any(Class class) и другие.Все они говорят сами за себя. Учебник по Mockito .

@Before
public void init (){
    MockitoAnnotations.initMocks(this);

    HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);

    Mockito.when(restTemplate.getForEntity(ArgumentMatchers.eq("theUrl"),ArgumentMatchers.any(Map.class)))
            .thenReturn(new ResponseEntity <Map>(someMap, HttpStatus.OK));
}

Относительно вашей структуры. Таким способом вы можете ввести RestTemplate через конструктор.

public class ServiceTester {

    @Mock
    private RestTemplate restTemplate;

    private Service service;

    @Before
    public void init (){
        MockitoAnnotations.initMocks(this);

        service = new Service(restTemplate);

        HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);

        Mockito.when(restTemplate.getForEntity(ArgumentMatchers.eq("theUrl"),ArgumentMatchers.any(Map.class)))
                .thenReturn(new ResponseEntity <Map>(someMap, HttpStatus.OK));
    }


}

class Service {

    private RestTemplate template;

    @Autowired
    public Service(RestTemplate template) {
        this.template = template;
    }

    public Map doSomething () {
        // do something with template
    }
}
0 голосов
/ 04 июля 2019

Вы уверены, что хотите издеваться, особенно шаблон отдыха?

Как насчет не издеваться над шаблоном restTemplate, а вместо этого издеваться над ответом?

Это также поможет вам проверить поведение restTemplate. Что, если restTemplate получит 404 или 500?

Именно поэтому я предлагаю вам использовать MockRestServiceServer

Это помогает проверить все реальные сценарии.

0 голосов
/ 04 июля 2019

Вы должны ввести RestTemplate свой сервис SomeService. В настоящее время вы создаете новый экземпляр в сервисе. Это означает, что вы не получите фиктивный экземпляр RestTemplate, но вы получите новый новый экземпляр реального класса RestTemplate.

Вы должны сделать что-то вроде этого:

class SomeService
{
   @Inject
   private RestTemplate restTemplate;   

   //some private, static,  final data members
   public Map getService(String sNo, String uId, String en)
   {
      ResponseEntity <Map> response = restTEmplate.getForEntity("https://someurl.com/someService", 
      Map.class);
      ...
   }
}
0 голосов
/ 04 июля 2019

Если вам разрешено вносить изменения в класс SomeService, я бы порекомендовал вам сделать следующее:

class SomeService
{
   //some private, static,  final data members
   public Map getService(String sNo, String uId, String en)
   {
      ResponseEntity <Map> response = getForEntity("https://someurl.com/someService", Map.class);
      Map body = response.getBody();
      //do something

      HttpEntity<?> request = new HttpEntity <>(payLoad, headers);
      //payload is Hash Map and headers is a LinkedMultiValueMap
      ResponseEntity <Map> response = postForEntity(url, request, headers);
      return response.getBody(); 
   }   
}

Как вы уже догадались, методы getForEntity и postForEntity были извлечены, а RestTemplateсоздается внутри - выполняет свою работу под прикрытием.А поскольку вы хотели с самого начала издеваться над RestTemplate, хорошо, что мы от него избавились - теперь мы можем шпионить за нашим сервисом без каких-либо объектов для насмешек.

    @RunWith(MockitoJunitRunner.class)
    class TestSomeService
    {
       @InjectMocks
       @Spy
       SomeService ser;
       /*Some data members*/

       @Before
       {
          HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);

          doReturn(new ResponseEntity <Map>(someMap, HttpStatus.OK))
            .when(ser).getForEntity("theUrl", Map.class));

          doReturn(new ResponseEntity <Map>(expectedMap, HttpStatus.OK))
            .when(ser).postForEntity("anotherUrl", request, Map.class));
       }

       @Test
       public void testGetService()
       {
           Map <String, Object> result = ser.getService("123", "abc", "QA");
       }    
    }
0 голосов
/ 04 июля 2019

Я макет шаблона отдыха вот так

@RunWith(SpringRunner.class)
public class Clazz {

    @Mock
    private RestTemplate restTemplate;
}

Поэтому попробуйте использовать SpringRunner вместо MockitoRunner, возможно, он будет работать

...