Mockito在被模拟类中模拟方法

xwmevbvl  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(298)

我试图模拟下面类中的方法,但无法做到,代码流进入实现方法,并导致nullPointerException。
这个类如下所示,我打算模拟的方法是getPredictionList(String,String)。

public class PredictionService {

        @Inject
        private ElasticSearch elasticSearch;

        private final RestHighLevelClient restHighLevelClient = OpenSearchRestHighLevelClient.getRestHighLevelClient();

        public String getPredictionList(String query, String index){

            try {
            //Method call successfully mocked
            SearchSourceBuilder searchSourceBuilder = elasticSearchEntity.createQuery(query);
            SearchRequest  searchRequest = new SearchRequest(index);
            searchRequest.source(searchSourceBuilder);

            //Method to be mocked
            SearchResponse serchResponse = getSearchResponse(searchRequest);

            //..code..//

            }catch(Exception e) {
                e.printStackTrace();
            }

            return 
        }

        public SearchResponse getSearchResponse(SearchRequest searchRequest){
            return restHighLevelClient.search(searchRequest, RequestOption.DEFAULT);
        }
    }

相应的测试类如下所示。
首先,我创建了一个PredictionService的模拟,然后注入了依赖项。

when(mockPredictionService.getSearchResponse(any())).thenReturn(searchResponse);

但是当代码执行时,这个模拟不存在,代码流入getSearchResponse实现并抛出空指针异常。

class PredictionServiceTest{

        //Write create a mock to test and inject the resources.

        @Spy
        @InjectMock
        PredictionService injectMockPredictionService;

        //Mock the resource 
        @Mock 
        ElasticSearchEntity mockElasticSearchEntity;

        @InjectMock
        PredictionService mockPredictionService;

        @Test
        public void getPredictionListTest() {

            //Mocking createQuery Response
            ElasticSearchEntity elasticSearchEntity = ElasticSearchEntity();
            SearchSourceBuilder searchSourceBuilder = elasticSearchEntity.createQuery("inputQuery");
            when(mockElasticSearchEntity.createQuery(any())).thenReturn(searchSourceBuilder);

            //Mocking searchResponse
            SearchResponse searchResponse = getDummySearchResponseImplementation();
            when(mockPredictionService.getSearchResponse(any())).thenReturn(searchResponse);

            String actualResponse = injectMockPredictionService.getPredictionList("inputQuery", "someIndex");       
        }

    }

如果我用injectMockPredictionService替换mockPredictionService,它会直接进入此行的实现方法,然后返回空指针异常。

when(mockPredictionService.getSearchResponse(any())).thenReturn(searchResponse);

已替换代码。

when(injectMockPredictionService.getSearchResponse(any())).thenReturn(searchResponse);

更新

我有两个PredictionService的模拟,

// To call the method
@Spy
@InjectMock
PredictionService injectMockPredictionService;

// To Provide mock for getSearchResponse Method
@InjectMock
PredictionService mockPredictionService;

根据链接,我已将实现更改为

@InjectMock
PredictionService injectMockPredictionService = Mockito.spy(new PredictionService ());

但这并没有帮助,代码进入实现类并抛出NULL指针异常.我已经更新了问题.

m1m5dgzv

m1m5dgzv1#

1.为PredictionService创建一个partial mock。你需要使用Spy mock。当你使用spy时,真正的方法被调用(除非方法被存根)。所以一些方法将被执行,而另一些将被模拟。
1.第二个问题是Spy注解不能与InjectMocks一起使用。请改用Mockito.spy

@org.mockito.InjectMocks
 PredictionService mockPredictionService = Mockito.spy(new PredictionService());

另一个选择是在PredictionService中创建一个构造函数,然后手动注入mock:

PredictionService mockPredictionService = Mockito.spy(new PredictionService(mockElasticSearch));

带注解的工作测试示例:

import org.junit.runner.RunWith;
import org.mockito.Mockito;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

@RunWith(org.mockito.junit.MockitoJUnitRunner.class)
public class PredictionServiceTest{
    @org.mockito.Mock
    ElasticSearch mockElasticSearch; //create mock for elastic search

    @org.mockito.InjectMocks
    PredictionService mockPredictionService = Mockito.spy(new PredictionService());// create partial mock for your service, because you mock only one method of real object
                                                                                   //inject mocks in your service

    @org.mockito.Mock
    SearchResponse searchResponse;//create a mock for the search response or you can create your own response without mock

    @org.junit.Test
    public void getPredictionListTest() {
        //perform mock of elastic search
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
        when(mockElasticSearch.createQuery(any())).thenReturn(searchSourceBuilder);

        //partially mock your service
        when(mockPredictionService.getSearchResponse(any())).thenReturn(searchResponse);

        //execute test
        String actualResponse = mockPredictionService.getPredictionList("inputQuery", "someIndex");

        //verify that mock was executed
        verify(mockPredictionService, times(1)).getSearchResponse(any());
    }
}

相关问题