如何在 spring 启动时模拟 resttemplate 调用?

How to mock resttemplate calls in spring boot?

我尝试为调用第 3 方的服务中的其余调用编写测试用例 api。

@RunWith(MockitoJUnitRunner.class)
public class ForceServiceTest {
private ForceService forceService;
@Mock
private ForceServiceConfig config;
@Mock
private RestTemplate restTemplate;

@Before
public void setup() {
    forceService = new ForceService(config);
}

@Test
public void apiCall_valid() throws JSONException {
    HttpHeaders headers = new HttpHeaders();
    headers.set(CONTENT_TYPE, "application/x-www-form-urlencoded");
    headers.set(ACCEPT, APPLICATION_JSON);
    HttpEntity<String> entity = new HttpEntity<>(
            "id=null",
            headers);
    config.authTokenUrl = "https://ex...com/..";
    Mockito.when(restTemplate.exchange(config.authTokenUrl, HttpMethod.POST, entity, Access.class)).thenReturn(null);
    // Mockito.when(any()).thenReturn(null);
    forceService.apiCall();
}

}

@Component
public class ForceService {
    private ForceServiceConfig config;
    private RestTemplate restTemplate = new RestTemplate();
public ForceService(ForceServiceConfig config) {

    this.config = config;
}
    private String apiCall() {
    HttpHeaders headers = new HttpHeaders();
    headers.set(CONTENT_TYPE, "application/x-www-form-urlencoded");
    headers.set(ACCEPT, APPLICATION_JSON);

    HttpEntity<String> entity = new HttpEntity<>(
            "&id=" + config.id,
            headers);
    ResponseEntity<Access> response = restTemplate.exchange(config.authTokenUrl, HttpMethod.POST, entity,
            Access.class);
    return response.getBody().token_type + " " + response.getBody().access_token;
     }

}

我收到以下错误:

org.springframework.web.client.HttpClientErrorException: 404 未找到 在 org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:78) 在 org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700) 在 org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)

它在测试 class 中调用 api,我不想发生这种情况。 我需要模拟第三方 api 的 resttemplate 调用。如果不实际调用 api 怎么办?

这就是问题所在

public class ForceService {
    private ForceServiceConfig config;
    private RestTemplate restTemplate = new RestTemplate(); // HERE

您正在创建新的 REAL 休息模板。你可能想要的是

  1. 使用您在包装测试中创建的模拟 class
  2. 使用真正的 rest 模板并对其进行监视。

不知道您的实际结构(1 个文件 2 classes),但可以安全地假设它不是,并且在任何情况下您都可以简单地将 RestTemplate 作为 ctor 参数传递。所以

@Component
public class ForceService {
    private ForceServiceConfig config;
    private RestTemplate restTemplate;
public ForceService(ForceServiceConfig config,RestTemplate restTemplate) {
    this.restTemplate=restTemplate;
    this.config = config;
}

@Before
public void setup() {
    forceService = new ForceService(config,restTemplate);
}

现在,如果您希望 RestTemplate 只是一个几乎什么都不做的存根,并且如果没有其他指示,则在任何调用中 return 为 null - 将其保留为 @Mock.

但是,如果你想让它正常工作并且只拦截一些特定的方法调用和存根响应,请使用 spy。

@Mock
private RestTemplate restTemplate;
private RestTemplate restTemplate=Mockito.mock(RestTemplate.class)

private RestTemplate restTemplate=Mockito.spy(new RestTemplate());