Один ложный класс работает нормально, другой возвращает ноль - PullRequest
0 голосов
/ 05 ноября 2019

В одном из моих модульных тестов я высмеиваю 2 класса, определяя поведение с помощью Mockito. Когда и затем вызывается функция.

Один из проверенных классов работает точно так, как ожидалось, другой возвращает null. Я не могу понять, в чем разница между ними.

QueryServiceTest.java

@Import({ QueryServiceTestConfig.class })
@RunWith(SpringRunner.class)
public class QueryServiceTest {

    @Autowired
    private QueryService queryService;
    @MockBean
    private ElasticConnectionService elasticConnectionService;
    @MockBean
    private HBaseConnectionService hbaseConnectionService;

    @Test
    public void test_getRecordsFromQuery() throws IOException {

        // creation of sample data for inputs and outputs goes here

        // This mock works when called from queryService.getRecordsFromQuery()
        when(elasticConnectionService.getRowIdsFromQuery(filterParams, testIndex)).thenReturn(getRowIdsFromQuery_result);

        List<JSONObject> matches = queryService.getMatchingRowIds(getRowIdsFromQuery_result);

        // matchesArray is directly defined to make sure its exactly the same as in queryService.getRecordsFromQuery()
        JSONObject matchesArray = new JSONObject("{\"testTable\":[\"testUUID\"]}");

        // This mock fails when called from queryService.getRecordsFromQuery()
        when(hbaseConnectionService.getRowsByIDs(matchesArray)).thenReturn(getRowsByIDs_result);

        // This returns getRowsByIDs_result as expected
        JSONArray test = hbaseConnectionService.getRowsByIDs(matchesArray);

        // This returns null
        JSONArray actual = new JSONArray(queryService.getRecordsFromQuery(filterParams, testIndex));
    }
}

QueryService.java

@Service
public class QueryService {

    @Autowired
    private ElasticConnectionService elasticConnectionService;
    @Autowired
    private HBaseConnectionService hbaseConnectionService;
    @Autowired
    private PSQLConnectionService psqlConnectionService;

    public String getRecordsFromQuery(
                    Map<String,String> filterParams,
                    String tablename) throws IOException {
        /**
         * Get records that match simple key/value filters
         */

        // This mocked method returns exactly what was expected
        List<List<JSONObject>> lookupsList = elasticConnectionService.getRowIdsFromQuery(filterParams, tablename);

        List<JSONObject> matches = getMatchingRowIds(lookupsList);

        // matchesArray is exactly the same as in the test class
        JSONObject matchesArray = new JSONObject("{\"testTable\":[\"testUUID\"]}");

        // This returns null
        JSONArray hbResults = hbaseConnectionService.getRowsByIDs(matchesArray);

        return hbResults.toString(4);
    }
}

QueryServiceTestConfig.java

@Configuration
public class QueryServiceTestConfig {

    @Bean
    public QueryService queryService() {
        return new QueryService();
    }

    @Bean
    public ElasticConnectionService elasticConnectionService() {
        return new ElasticConnectionService();
    }

    @Bean
    public HBaseConnectionService hbaseConnectionService() {
        return new HBaseConnectionService();
    }

    @Bean
    public PSQLConnectionService psqlConnectionService() {
        return new PSQLConnectionService();
    }
}

Что меня больше всего смущает, так это то, что в queryService.getRecordsByQuery() макет elasticConnectionService.getRowIDsFromQuery() возвращает то, что ожидалось, но hbaseConnectionService.getRowsByIDs()макет возвращает null.

Классы обслуживания эластичного соединения и соединения hbase определены в одной и той же папке, и единственная аннотация, которую они имеют, - @Service. Я думаю, что я настроил что-то не так, если оба не удаются, но тот факт, что вызов elasticConnectionService работает, как и ожидалось, говорит мне о том, что происходит что-то еще.

1 Ответ

1 голос
/ 05 ноября 2019

Если пакет JSONObject равен org.json, метод равных JSONObject выглядит следующим образом:

public boolean equals(Object object) {
            return object == null || object == this;
        }

Поскольку экземпляр matchesArray в QueryService отличается от экземплярав QueryServiceTest метод equals() вернет false.

Попробуйте изменить это:

when(hbaseConnectionService.getRowsByIDs(matchesArray)).thenReturn(getRowsByIDs_result);

на это и посмотрите, изменятся ли ваши результаты:

when(hbaseConnectionService.getRowsByIDs(Mockito.any())).thenReturn(getRowsByIDs_result);

Я думаю, что вы также можете сделать это:

when(hbaseConnectionService.getRowsByIDs(Mockito.eq(matchesArray))).thenReturn(getRowsByIDs_result);

или:

when(hbaseConnectionService.getRowsByIDs(Matchers.eq(matchesArray))).thenReturn(getRowsByIDs_result);

Поскольку метод Matchers.eq() под капотом, вероятно, вызывает JSONObject.equals(),Matcher, вероятно, не будет работать (я не проверял исходный код для Matchers.eq()).

В общем, когда вы устанавливаете вызов метода mock, вы хотите поместить parameter(s) в один из Mockito. Методы Матчера. К сожалению, в вашем сценарии это не сработает.

(обратите внимание, что класс Mockito расширяет Matchers)

...