簡體   English   中英

使用 when + thenReturn 時 Mockito 和泛型的問題

[英]Issue with Mockito and Generics when using when + thenReturn

我一直在網上尋找很多關於這個問題的信息,但我找到的解決方案都沒有對我有用。

我有一個測試類,以及我試圖測試的服務。

在測試類中:

public class ElasticSearchSearchServiceImplTest{

@InjectMocks
private ElasticSearchSearchServiceImpl elasticSearchSearchService = new ElasticSearchSearchServiceImpl();

private SearchMyListCriteria searchMyListCriteria;

private SearchHitListCriteria searchHitListCriteria;

private SearchFieldLimitsCriteria searchFieldLimitsCriteria;

private SearchDetailCriteria searchDetailCriteria;

private SearchBrowseCriteria searchBrowseCriteria;

@Mock
private SearchRequestBuilder searchRequestBuilder;

@Mock
private SecurityService securityService;

@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Client client;

@Mock
private ListenableActionFuture<SearchResponse> listenableActionFuture;

@BeforeMethod
public void setup() throws InterruptedException
{
    MockitoAnnotations.initMocks(this);
    SearchResponse sr = new SearchResponse();
    Mockito.when(client.prepareSearch(Mockito.anyString())
            .setQuery(Mockito.any(QueryBuilder.class))
            .addFields(Mockito.anyObject())
            .setFrom(Mockito.anyInt())
            .setSize(Mockito.anyInt())
            ).thenReturn(searchRequestBuilder);
    Mockito.when(securityService.isAccountabilityEnabled()).thenReturn(false);

    Mockito.when(searchRequestBuilder.execute()).thenReturn(listenableActionFuture);
    Mockito.when(listenableActionFuture.actionGet()).thenReturn(sr);

    searchMyListCriteria = buildSearchCriteriaBase();
    searchHitListCriteria = buildSearchHitListCriteria();
    searchFieldLimitsCriteria = buildSearchFieldLimitsCriteria();
    searchDetailCriteria = buildSearchDetailCriteria();
    searchBrowseCriteria = buildSearchBrowseCriteria();
}

@Test
public void testDoMyListSearch()
{
    SearchResponse searchResponse = new SearchResponse();
    Boolean execOk = false;
    try {
        searchResponse = elasticSearchSearchService.doMyListSearch(searchMyListCriteria);
        Assert.assertNotNull(searchResponse);
        execOk = true;
    }catch (Exception e){
        e.printStackTrace();
    }
    Assert.assertTrue(execOk);
}

然后,在 ElasticSearchSearchServiceImpl.java 中,我在測試中調用了這個方法:

@Override
public SearchResponse doMyListSearch(SearchMyListCriteria criteria) throws Exception
{
    SearchTimer t = new SearchTimer();
    SearchResponse resp = null;
    int size = criteria.getDocIds().size();
    if(!criteria.getDocIds().isEmpty())
    {
        String indexName = getSearchAlias(criteria);
        String[] ids = criteria.getDocIds().toArray(new String[criteria.getDocIds().size()]);
        IdsQueryBuilder qb = QueryBuilders.idsQuery(getESTypes(criteria));
        qb.addIds(ids);

        SearchDataSourceAccountabilityEnum requiredAcc = securityService.isAccountabilityEnabled() && !criteria.getPermissions().isSuperUser()
                ? getAccountabilityForDataSources(criteria)
                : SearchDataSourceAccountabilityEnum.NONE;
        List<QueryBuilder> filters = new ArrayList<>();
        addSecurityToFilter(filters, criteria, requiredAcc);
        QueryBuilder filter = ElasticSearchUtils.and(filters);
        QueryBuilder fqb = filter == null ? qb : QueryBuilders.boolQuery().must(qb).filter(filter);

        SearchRequestBuilder req = client.prepareSearch(indexName)
                                         .setQuery(fqb)
                                         .addFields(determineMyListFieldsToReturn(criteria))
                                         .setFrom(0)
                                         .setSize(size);

        resp = req.execute().actionGet();
    }

    long searchMillis = t.getElapsedMillis();
    logPerform("Query Execution time for my list search " + criteria.toString() + COLON_SPACE + searchMillis + MILLISECONDS_MARKER);
return resp;
}

問題是,當它在“resp = req.execute().actionGet();”行通過 ElasticSearchSearchServiceImpl#doMyListSearch 時它拋出以下異常:

java.lang.ClassCastException: org.mockito.internal.creation.cglib.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$db3b9e0a cannot be cast to org.elasticsearch.action.search.SearchResponse
at com.sirsidynix.bcss.search.biz.svc.impl.ElasticSearchSearchServiceImpl.doMyListSearch(ElasticSearchSearchServiceImpl.java:228)
at com.sirsidynix.bcss.search.biz.svc.impl.ElasticSearchSearchServiceImplTest.testDoMyListSearch(ElasticSearchSearchServiceImplTest.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1123)
at org.testng.TestNG.run(TestNG.java:1031)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)

我已經嘗試了網絡中的大多數解決方案,但似乎沒有任何效果對我有用。 請如果你有建議,我很感激。

問候!

您是否嘗試將測試減少到導致測試失敗的最小代碼段?

你認為這是泛型的問題。 如果是這樣,那么像下面這樣簡單的事情也會失敗:

@Mock
private ListenableActionFuture<SearchResponse> listenableActionFuture;

@BeforeMethod
public void setup() throws InterruptedException {
    MockitoAnnotations.initMocks(this);
    SearchResponse sr = new SearchResponse();
    Mockito.when(listenableActionFuture.actionGet()).thenReturn(sr);
}

@Test
public void testDoMyListSearch() {
    SearchResponse sr = listenableActionFuture.actionGet();
}

可以? 我的猜測不是..我認為這更有可能是由於深存根以及深存根返回與您在thenReturn返回的模擬相同類型的模擬thenReturn 我想知道是否有必要使用thenReturn ,或者深度存根是否會讓它“神奇地”工作。

無論如何,我的建議是不斷減少空間以找到問題所在。 此外,刪除諸如searchDetailCriteria類的不必要的內容將有助於人們理解代碼並更快地幫助您。

(對不起,我更願意發表評論,但沒有足夠的聲譽)。

我認為客戶端會為某些方法調用返回一個 SearchRequestBuilder。 所以你可能需要模擬一個 SearchRequestBuilder。 您能否在存根客戶端之前嘗試添加以下內容。

@BeforeMethod
public void setup() throws InterruptedException
{
MockitoAnnotations.initMocks(this);
SearchResponse sr = new SearchResponse();

SearchRequestBuilder requestBuilder = mock(SearchRequestBuilder.class, RETURNS_DEEP_STUBS);
when(client.prepareSearch(Matchers.any())).thenReturn(requestBuilder);
when(requestBuilder.setQuery(Matchers.any())).thenReturn(requestBuilder);
when(requestBuilder.addFields(Matchers.any())).thenReturn(requestBuilder);
when(requestBuilder.setFrom(Matchers.anyInt())).thenReturn(requestBuilder);
when(requestBuilder.setSize(Matchers.anyInt())).thenReturn(requestBuilder);

MockitoAnnotations.initMocks(this);
SearchResponse sr = new SearchResponse();
Mockito.when(client.prepareSearch(Mockito.anyString())
        .setQuery(Mockito.any(QueryBuilder.class))
        .addFields(Mockito.anyObject())
        .setFrom(Mockito.anyInt())
        .setSize(Mockito.anyInt())
        ).thenReturn(searchRequestBuilder);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM