Как создать тестовые наборы Junit для лямбда-выражения с помощью Mockito Junit 5?

#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» ?