[英]How to mock RestTemplate with MockRestServiceServer?
@RunWith(MockitoJUnitRunner.class)
public class FeatureFlipperManagerTest {
@Autowired
RestTemplate restTemplate = new RestTemplate();
@Autowired
Service service = new Service();
MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
@Test
public void test() throws Exception {
mockServer.expect(requestTo(Mockito.anyString()))
.andRespond(withSuccess("{\"enabled\":true}", MediaType.APPLICATION_JSON));
boolean res = service.isEnabled("xxx");
mockServer.verify();
Assert.assertEquals(true, res);
}
}
I have MockRestServiceServer to mock restTemplete in a service.我有 MockRestServiceServer 来模拟服务中的 restTemplete。 But it always fail.但它总是失败。 it shows the error as java.lang.AssertionError: Further request(s) expected 0 out of 1 were executed
.它将错误显示为java.lang.AssertionError: Further request(s) expected 0 out of 1 were executed
。 Any one could let me know where I did not do it right.任何人都可以让我知道我哪里做得不对。
The service itself will looks as this:服务本身将如下所示:
public class Service{
public boolean isEnabled(String xxx) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
if(...)return true;
return false;
}
}
First of all, your Service
class creates a new instance of RestTemplate on every request.首先,您的Service
类为每个请求创建一个 RestTemplate 的新实例。 I cannot stress enough how bad practice it is.我怎么强调这是多么糟糕的做法。 Create a bean of type RestTemplate and inject it into your Service
bean (it is most likely already created - depending on the Spring MVC version you are using).创建一个 RestTemplate 类型的 bean 并将其注入您的Service
bean(它很可能已经创建 - 取决于您使用的 Spring MVC 版本)。
Once you have it, then both RestTemplates: one in your Service
bean and one injected into FeatureFlipperManagerTest
will be the same and testing with MockRestServiceServer
will be possible.一旦你有了它,那么两个 RestTemplates:一个在你的Service
bean 中和一个注入到FeatureFlipperManagerTest
将是相同的,并且可以使用MockRestServiceServer
进行测试。
EDIT - to be more explicit:编辑 - 更明确:
Modify your Service
class to:将您的Service
类修改为:
@Component
public class Service {
private RestTemplate restTemplate;
@Autowired
public Service(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public boolean isEnabled(String xxx) {
ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
if(...)return true;
return false;
}
}
and your test class to:和您的测试类:
@RunWith(MockitoJUnitRunner.class)
public class FeatureFlipperManagerTest {
@Autowired
RestTemplate restTemplate;
@Autowired
Service service;
MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
@Test
public void test() throws Exception {
mockServer.expect(requestTo(Mockito.anyString()))
.andRespond(withSuccess("{\"enabled\":true}", MediaType.APPLICATION_JSON));
boolean res = service.isEnabled("xxx");
mockServer.verify();
Assert.assertEquals(true, res);
}
}
If this fails with exception saying that there is no RestTemplate
bean present then please paste info about version of Spring (Spring Boot?) you are using.如果此操作失败并显示不存在RestTemplate
bean 的异常,请粘贴有关您正在使用的 Spring(Spring Boot?)版本的信息。
I think you mean you want to use RestTemplate which is provided by spring, so you should createServer after the spring autowired the RestTemplate.我想你的意思是你想使用 spring 提供的 RestTemplate,所以你应该在 spring 自动装配 RestTemplate 之后 createServer。 I think you can do it like this:我认为你可以这样做:
@RunWith(MockitoJUnitRunner.class)
public class FeatureFlipperManagerTest {
@Autowired
RestTemplate restTemplate;
Service service;
MockRestServiceServer mockServer;
@Before
public void init() {
service = new Service();
service.setRestTemplate(restTemplate);
// If you have autowired restTemplate in Service, you can just autowired the service
mockServer = MockRestServiceServer.createServer(restTemplate);
}
@Test
public void test() throws Exception {
mockServer.expect(requestTo(Mockito.anyString()))
.andRespond(withSuccess("{\"enabled\":true}", MediaType.APPLICATION_JSON));
boolean res = service.isEnabled("xxx");
mockServer.verify();
Assert.assertEquals(true, res);
}
}
This is not an answer to your question, but just in case anyone comes across this question in 2021… With Spring Boot Testing, you may want to take advantage of testing the REST slice only with @RestClientTest
.这不是您问题的答案,但以防万一有人在 2021 年遇到这个问题……使用 Spring Boot 测试,您可能希望仅使用@RestClientTest
来测试 REST 切片。 This creates a RestTemplateBuilder
bean only by default, if you want an auto-wired RestTemplate
just add one bit of configuration as below.这只会在默认情况下创建一个RestTemplateBuilder
bean,如果你想要一个自动连接的RestTemplate
只需添加一点配置,如下所示。 (The example is in Kotlin, using Java instead remains as an excercise to the reader.) (这个例子在 Kotlin 中,使用 Java 仍然是读者的练习。)
@AutoConfigureWebClient(registerRestTemplate = true)
@RestClientTest(Service::class)
class AdkClientTest @Autowired constructor(
private val mockRestServiceServer: MockRestServiceServer,
private val service: Service
) {
// …
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.