繁体   English   中英

如何使用 MockRestServiceServer 模拟 RestTemplate?

[英]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);
    }
}

我有 MockRestServiceServer 来模拟服务中的 restTemplete。 但它总是失败。 它将错误显示为java.lang.AssertionError: Further request(s) expected 0 out of 1 were executed 任何人都可以让我知道我哪里做得不对。

服务本身将如下所示:

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

首先,您的Service类为每个请求创建一个 RestTemplate 的新实例。 我怎么强调这是多么糟糕的做法。 创建一个 RestTemplate 类型的 bean 并将其注入您的Service bean(它很可能已经创建 - 取决于您使用的 Spring MVC 版本)。

一旦你有了它,那么两个 RestTemplates:一个在你的Service bean 中和一个注入到FeatureFlipperManagerTest将是相同的,并且可以使用MockRestServiceServer进行测试。

编辑 - 更明确:

将您的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;
    }
}

和您的测试类:

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

如果此操作失败并显示不存在RestTemplate bean 的异常,请粘贴有关您正在使用的 Spring(Spring Boot?)版本的信息。

我想你的意思是你想使用 spring 提供的 RestTemplate,所以你应该在 spring 自动装配 RestTemplate 之后 createServer。 我认为你可以这样做:

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

这不是您问题的答案,但以防万一有人在 2021 年遇到这个问题……使用 Spring Boot 测试,您可能希望仅使用@RestClientTest来测试 REST 切片。 这只会在默认情况下创建一个RestTemplateBuilder bean,如果你想要一个自动连接的RestTemplate只需添加一点配置,如下所示。 (这个例子在 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM