#java #lambda #mockito #junit5
Вопрос:
Я хочу создать тестовые примеры метода Junit, в которых мы выполняем итерацию Listlt;Maplt;String,Objectgt;gt;
с использованием цикла forEach с лямбда-выражением. Теперь я хочу высмеять утверждение objectMapper.writeValueAsString(recordObj.get("value"));
, но я не понимаю, как его использовать recordObj
.
public String apply(MyRequestWrapper requestWrapper) { String resultStr=null; final Maplt;String, Listlt;PubSubEventgt;gt; packagesEventList = AppUtilities.getPackagesEventsMappedList(); try { logger.debug("Received Record:: " requestWrapper.getBody().toString()); Listlt;RecordProcessedResultgt; results = new ArrayListlt;gt;(); Listlt;Maplt;String,Objectgt;gt; recordMaps= string2List(objectMapper,requestWrapper.getBody().toString()); logger.debug("Parsed received payload ::: " LocalDateTime.now() " batch size is ::: " recordMaps.size()); if(! ObjectUtils.isEmpty(recordMaps) amp;amp; !recordMaps.isEmpty() ) { recordMaps.forEach(recordObj -gt;{ ConsumerRecord record=objectMapper.convertValue(recordObj, ConsumerRecord.class); String topicName = recordObj.get("topic").toString(); String key = null; String value = null; String offset = null; String xTraceabilityId = ((Maplt;String, Stringgt;) recordObj.get("headers")).get(IdTypeConstants.XTRACEABILITYID); String xCorrelationId = ((Maplt;String, Stringgt;) recordObj.get("headers")).get(IdTypeConstants.XCORRELATIONID); MDC.put(IdTypeConstants.XTRACEABILITYID, xTraceabilityId); MDC.put(IdTypeConstants.XCORRELATIONID, xCorrelationId); try { key = objectMapper.writeValueAsString(recordObj.get("key")); value = objectMapper.writeValueAsString(recordObj.get("value")); offset = objectMapper.writeValueAsString(recordObj.get("offset")); MyEvent myEvent= objectMapper.readValue(value, MyEvent.class); subscribedPackageProcessor.setInput(input); subscribedPackageProcessor.setOutput(output); subscribedPackageProcessor.setPackagesEventList(packagesEventList); subscribedPackageProcessor.setRequesterType(requesterType); subscribedPackageProcessor.processSubscribedPackage(myEvent.getPackageId()); RecordProcessedResult rpr = new RecordProcessedResult(record, true, null, xTraceabilityId, xCorrelationId, key, System.currentTimeMillis()); results.add(rpr); } catch(Exception e) { RecordProcessedResult rpr = new RecordProcessedResult(record, false, ExceptionUtils.getStackTrace(e), xTraceabilityId, xCorrelationId, key, System.currentTimeMillis()); results.add(rpr); logger.info("Exception occured while processing fund data :::out ", e); } MDC.clear(); }); } resultStr = objectMapper.writeValueAsString(results); }catch (Exception e) { logger.debug(e.getMessage()); } return resultStr; }
Я пробовал следовать тестовым наборам.
@Test void applyTest() throws Exception { MyEvent myEvent = new MyEvent(); myEvent.setPackageId("test"); MyRequestWrapper flowRequestWrapper= getMyRequestWrapper(); Listlt;Maplt;String, Objectgt;gt; maps = string2List(objectMapper1, flowRequestWrapper.getBody().toString()); Maplt;String,Objectgt; map = new HashMaplt;String, Objectgt;(); Mockito.when(objectMapper.readValue(Mockito.anyString(), Mockito.any(TypeReference.class))).thenReturn(maps); Mockito.when(objectMapper.writeValueAsString(Mockito.anyString())).thenReturn("test"); Mockito.when(objectMapper.readValue(Mockito.anyString(), Mockito.eq(MyEvent.class))).thenReturn(myEvent); //doNothing().when(subscribedPackageProcessor).processSubscribedPackage(""); String response = processESignCompletedEventSvcFlow.apply(flowRequestWrapper); Assertions.assertNotNull(response); }
Пожалуйста, помогите, Спасибо
Ответ №1:
Ваш метод слишком сложен для модульного тестирования. Например, он объявляет зависимости, вызывая методы в том же классе. Вы не можете издеваться над ними, и это во много раз усложняет тестирование.
Listlt;Maplt;String,Objectgt;gt; recordMaps = string2List(objectMapper,requestWrapper.getBody().toString());
Вам нужно извлечь string2List
метод в отдельный класс (с его собственными модульными тестами), который вводится в ваш класс в качестве зависимости.
Затем вы можете просто издеваться над string2List
классом, и когда вы это сделаете, вы будете управлять созданием recordObj
экземпляров из своего модульного теста для этого метода.
Ваш второй «грех» — злоупотребление лямбдами, создавая одну, которая длиннее двух строк. Лямбды должны быть короткими. если они занимают более нескольких строк, они должны быть извлечены в отдельный класс, который может быть протестирован отдельно. И снова, когда вы извлекли эту лямбду в отдельный класс и провели ее модульное тестирование, вы не можете просто включить « new RecordObjConsumer(results)
» в свой метод, так как это создает жестко запрограммированную зависимость, которую вы снова не можете издеваться. Вам нужно спроектировать потребителя таким образом, чтобы он мог быть введен в ваш класс в качестве внешней зависимости.
Комментарии:
1. Спасибо за предложение Торбен
2. Спасибо за предложение, Торбен, но если мы оставим сложность функции в стороне и будем оптимизированы в дальнейшем, не могли бы вы предложить, как использовать «Карты записей.forEach(recordObj -gt;{» в качестве макета, чтобы я мог использовать это в «Mockito.when» ?