Java 模拟私有最终字段或响应表单 RestHighLevelClient

Java Mocking a private final field or response form RestHighLevelClient

我正在尝试为以下方法编写测试用例,我需要模拟从弹性搜索数据库获得的响应。

@Inject
ESEntity mockElasticSearchEntity;
private final RestHighLevelClient restHighLevelClient = OpenSearchRestHighLevelClient.getRestHighLevelClient();

public String getAllMoviesListResult(String index){
    SourceBuilder sourceBuilder = entity.createElasticSearchQueryForGetAllMovieList();
    SearchRequest searchRequest = new SearchRequest(index);
    searchRequest.source(sourceBuilder);

    SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOption.DEFAULT);
    return searchResponse.getHits().get(0);
}

我写了下面的测试用例: 代码没有获得模拟响应,而是流向 RestHighLevelClient class 和 returns NullPointException。

@InjectMock
ESEntity mockElasticSearchEntity;

@Test
public void testgetAllMoviesListResult(){
    ESEntity elasticSearchEntity = new ESearchEntity();
    SearchSourceBuilder sourceBuilder = elasticSearchEntity.createElasticSearchQueryForGetAllMovieList();
    when(mockElasticSearchEntity.createElasticSearchQueryForGetAllMovieList()).thenReturn(sourceBuilder);
    
    String esReponse ="";
    JsonXContentParser xContentParser = new JsonXContentParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new JsonFactory().createParser(esResponse));
    SearchResponse searchResponse = SearchResponse.fromXContent(xContentParser);

    RestHighLevelClient mockRestHighLevelClient = mock(RestHighLevelClient.class);
    when(mockRestHighLevelClient.search(any(),any())).thenReturn(searchResponse);
    
    String actualResponse = new EntityService().getAllMoviesListResult("someIndex");
    
}

我搜索了类似的问题,但需要使用 PowerMock,而我当前使用的框架不支持它。

更新

public class OpenSearchRestHighLevelClient {

    private static RestHighLevelClient restHighLevelClient = null;
    
    public static RestHighLevelClient getRestHighLevelClient() {     
        //singleton implementation on receiving the RestHighLevelClient.
        if(restHighLevelClient==null) {
            restHighLevelClient = createRestHighLevelClient();
        }
        return restHighLevelClient;
    }
    
    public static RestHighLevelClient createRestHighLevelClient(){
        //logic to create RestHighLevelClient
    }
}

有一个我能想到的解决方法,您可以使用 mock static(checkout) 模拟 RestHighLevelClient 对象创建的静态方法 https://mvnrepository.com/artifact/org.mockito/mockito-inline

我正在使用 Gradle testImplementation 'org.mockito:mockito-inline:3.4.6' 这对我有用,让我知道

    @Test
    public void testgetAllMoviesListResult() {
        ESEntity elasticSearchEntity = new ESearchEntity();
        SearchSourceBuilder sourceBuilder = elasticSearchEntity.createElasticSearchQueryForGetAllMovieList();
        when(mockElasticSearchEntity.createElasticSearchQueryForGetAllMovieList()).thenReturn(sourceBuilder);

        String esReponse = "";
        JsonXContentParser xContentParser = new JsonXContentParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new JsonFactory().createParser(esResponse));
        SearchResponse searchResponse = SearchResponse.fromXContent(xContentParser);

        RestHighLevelClient mockRestHighLevelClient = mock(RestHighLevelClient.class);
        when(mockRestHighLevelClient.search(any(), any())).thenReturn(searchResponse);
        
        try (MockedStatic<OpenSearchRestHighLevelClient> openSearchRestHighLevelClient = mockStatic(OpenSearchRestHighLevelClient.class)) {
            openSearchRestHighLevelClient.when(OpenSearchRestHighLevelClient::getRestHighLevelClient).thenReturn(mockRestHighLevelClient);
            String actualResponse = new EntityService().getAllMoviesListResult("someIndex");
            assertEquals(expectedResponse, actualResponse);
        }

    }