我如何模拟Rest Template的getForEntity()方法

时间:2019-07-04 18:51:36

标签: java mockito junit4 resttemplate

我对Mockito还是陌生的,需要一些帮助,可能是一些有关如何模拟Rest Template的getForEntity和postForEntity方法的示例。下面是我要通过模拟getForEntity方法编写Junit测试用例的代码。

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 个答案:

答案 0 :(得分:1)

调用特定值时,必须用ArgumentMatchers.eq()包装。但是,您也可以使用anyString()any(Class class)和其他名称。他们都是不言自明的。 Mockito tutorial

@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
    }
}

答案 1 :(得分:0)

我像这样模拟一个休息模板

@RunWith(SpringRunner.class)
public class Clazz {

    @Mock
    private RestTemplate restTemplate;
}

因此,请尝试使用SpringRunner而不是MockitoRunner

答案 2 :(得分:0)

如果您被授权对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(); 
   }   
}

您可能已经猜到getForEntitypostForEntity方法已被提取出来,并且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");
       }    
    }

答案 3 :(得分:0)

您必须注入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);
      ...
   }
}

答案 4 :(得分:0)

您确定要模拟一个restTemplate吗?

不模拟剩余模板而是模拟答案呢?

它还将帮助您测试restTemplate行为。如果restTemplate得到404或500怎么办?

这就是为什么我建议您使用MockRestServiceServer

它有助于检查所有现实情况。