Java 如何在单元测试中模拟RESTAPI?

Java 如何在单元测试中模拟RESTAPI?,java,spring,post,mocking,resttemplate,Java,Spring,Post,Mocking,Resttemplate,我正在使用restemplateexchange-HttpMethod.POST方法发布到端点。在我的测试文件中,我正在测试POST方法的成功。然而,在我当前的测试中,当发出POST请求时,我得到了401个未经授权的错误。我需要帮助来模拟API,同时在测试文件中发出POST请求 @RunWith(MockitoJUnitRunner.class) @TestPropertySource public class DataTestRepoTest { private static fin

我正在使用restemplate
exchange-HttpMethod.POST
方法发布到端点。在我的测试文件中,我正在测试POST方法的
成功
。然而,在我当前的测试中,当发出POST请求时,我得到了
401个未经授权的错误
。我需要帮助来模拟API,同时在测试文件中发出POST请求

@RunWith(MockitoJUnitRunner.class)
@TestPropertySource
public class DataTestRepoTest {

    private static final String url = "http://localhost:8080/data/name";

    @Mock
    private DataTestRepo DataTestRepo;
    RestTemplate restTemplate = new RestTemplate();

    @Test
    public void restTemplateHttpPost_success() throws URISyntaxException {
        URI uri = new URI(url);
        Set<String> mockData = Stream.of("A","B").collect(Collectors.toSet());
        Map<String, String> body = new HashMap<>();
        body.put("Name", "Aws");
        JSONObject jsonObject = new JSONObject(body);

        HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);

        ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
                new HttpEntity<>(request, DataTestRepo.getHttpHeaders()), String.class);

        Assert.assertEquals(201, result.getStatusCodeValue());
    }
}


这是我的主要文件


@Component
public class DataTestRepo {

    private final RestTemplate restTemplate;
    private final String url;
    private final AllBuilder headersBuilder;

    public DataTestRepo(
            @Qualifier(Oauth.BEAN_NAME) AllBuilder headersBuilder,
            RestTemplate restTemplate, String url) {
        this.headersBuilder = headersBuilder;
        this.restTemplate = restTemplate;
        this.url = url;
    }
    public ResponseEntity<String> postJson(Set<String> results) {
        ResponseEntity<String> result = null;

        try {
            JSONObject jsonObject = new JSONObject(body);

            HttpEntity<String> request = new HttpEntity<String>(jsonObject.toString(), null);
            restTemplate.getMessageConverters().add(stringConvertor);
            result = restTemplate.exchange(url, HttpMethod.POST,
                    new HttpEntity<>(request, getHttpHeaders()), String.class);
         } 
        return result;
    }
}

@组成部分
公共类DataTestRepo{
私有最终RestTemplate RestTemplate;
私有最终字符串url;
私人最终AllBuilder headersBuilder;
公共数据报告(
@限定符(Oauth.BEAN\u NAME)AllBuilder HeaderBuilder,
RestTemplate(RestTemplate,字符串url){
this.headersBuilder=headersBuilder;
this.restTemplate=restTemplate;
this.url=url;
}
公共响应postJson(设置结果){
ResponseEntity结果=空;
试一试{
JSONObject JSONObject=新的JSONObject(主体);
HttpEntity请求=新的HttpEntity(jsonObject.toString(),null);
restemplate.getMessageConverters().add(stringConvertor);
结果=restTemplate.exchange(url,HttpMethod.POST,
新的HttpEntity(请求,getHttpHeaders()),String.class);
} 
返回结果;
}
}
这是我的测试文件

@RunWith(MockitoJUnitRunner.class)
@TestPropertySource
public class DataTestRepoTest {

    private static final String url = "http://localhost:8080/data/name";

    @Mock
    private DataTestRepo DataTestRepo;
    RestTemplate restTemplate = new RestTemplate();

    @Test
    public void restTemplateHttpPost_success() throws URISyntaxException {
        URI uri = new URI(url);
        Set<String> mockData = Stream.of("A","B").collect(Collectors.toSet());
        Map<String, String> body = new HashMap<>();
        body.put("Name", "Aws");
        JSONObject jsonObject = new JSONObject(body);

        HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);

        ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
                new HttpEntity<>(request, DataTestRepo.getHttpHeaders()), String.class);

        Assert.assertEquals(201, result.getStatusCodeValue());
    }
}


@RunWith(MockitoJUnitRunner.class)
@TestPropertySource
公共类DataTestRepoTest{
私有静态最终字符串url=”http://localhost:8080/data/name";
@嘲弄
私有DataTestRepo DataTestRepo;
RestTemplate RestTemplate=新RestTemplate();
@试验
public void restTemplateHttpPost_success()引发URI语法异常{
URI=新的URI(url);
Set mockData=Stream.of(“A”,“B”).collect(Collectors.toSet());
Map body=newhashmap();
正文。填写(“名称”、“Aws”);
JSONObject JSONObject=新的JSONObject(主体);
HttpEntity请求=新的HttpEntity(jsonObject.toString(),null);
ResponseEntity result=restemplate.exchange(uri,HttpMethod.POST,
新的HttpEntity(请求,DataTestRepo.getHttpHeaders()),String.class);
Assert.assertEquals(201,result.getStatusCodeValue());
}
}

您正在测试DataTestRepo类内部的逻辑,因此不应该模拟它。 RestTemplate是DataTestRepo内部的一个依赖项,所以这正是您需要模拟的。 一般来说,在测试中应该是这样的:

@InjectMocks
private DataTestRepo DataTestRepo;
@Mock
RestTemplate restTemplate;
此外,还必须为模拟依赖项提供返回值,如下所示:

Mockito.when(restTemplate.exchange(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(new ResponseEntity<>(yourExpectedDataHere, HttpStatus.OK));
enter code here
Mockito.verify(restTemplate, Mockito.times(1)).exchange(ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere));

这是一本关于这个主题的好书:

我以前使用过上面的代码。我得到了
java.lang.NullPointerException
,所以我改为
RestTemplate RestTemplate=new RestTemplate()还有其他建议吗?感谢您获得了NPE,因为在逻辑中调用模拟依赖项时,它将返回null。您必须定义此模拟对象应返回的内容。我修改了我的答案,请看上面。你的意思是这样的
Mockito.when(restemplate.exchange(Mockito.eq(uri),Mockito.eq(HttpMethod.POST),Mockito.eq(new-HttpEntity(request,processorDispatcherRepositoryImpl.getHttpHeaders()),Mockito.eq(String.class))。然后返回(new-ResponseEntity(result,HttpStatus.OK));
然后是
Assert.assertEquals
?是的,但请记住您正在测试
DataTestRepo.postJson
,所以
Assert.assertEquals(您的预期数据,DataTestRepo.postJson(Set.of(“您的Stringshere”))这就是我尝试的
Mockito.verify(restemplate,Mockito.times(1)).exchange(Mockito.eq(uri),Mockito.eq(HttpMethod.POST),Mockito.eq(newhttpentity(request)),Mockito.eq(String.class));Assert.assertEquals(201,DataTestRepo.postJson(Stream.of(“A”,“B”).collect(Collectors.toSet())))----但是我得到了这个错误
类型Assert中的方法assertEquals(Object,Object)不适用于参数(int,void)
我做错什么了吗?