简体   繁体   English

如何使用 Mockito Junit 5 为 lambda 表达式创建 Junit 测试用例?

[英]How to create Junit testcases for lambda expression using Mockito Junit 5?

I want to create Junit TestCases of method, in which we are iterating List<Map<String,Object>> using forEach loop with lambda expresion.我想创建方法的 Junit 测试用例,其中我们使用带有 lambda 表达式的 forEach 循环迭代List<Map<String,Object>> Now I want to mock statement objectMapper.writeValueAsString(recordObj.get("value"));现在我想模拟语句objectMapper.writeValueAsString(recordObj.get("value")); but I am not understanding how to use recordObj .但我不明白如何使用recordObj

public String apply(MyRequestWrapper requestWrapper) {
        String resultStr=null;
        final Map<String, List<PubSubEvent>> packagesEventList = AppUtilities.getPackagesEventsMappedList();

        try {
            logger.debug("Received Record:: " + requestWrapper.getBody().toString());
            List<RecordProcessedResult> results = new ArrayList<>();
            List<Map<String,Object>> recordMaps= string2List(objectMapper,requestWrapper.getBody().toString());
            logger.debug("Parsed received payload ::: "+ LocalDateTime.now() + " batch size is ::: "+ recordMaps.size());
            
            
            if(! ObjectUtils.isEmpty(recordMaps) && !recordMaps.isEmpty() ) {
                recordMaps.forEach(recordObj ->{
                    ConsumerRecord record=objectMapper.convertValue(recordObj, ConsumerRecord.class);
                    String topicName = recordObj.get("topic").toString();
                    String key = null;
                    String value = null;
                    String offset = null;
                    String xTraceabilityId = ((Map<String, String>) recordObj.get("headers")).get(IdTypeConstants.XTRACEABILITYID);
                    String xCorrelationId = ((Map<String, String>) 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;
    }

I have tried following testcases.我尝试过以下测试用例。

@Test void applyTest() throws Exception { 
        MyEvent myEvent = new MyEvent(); 
        myEvent.setPackageId("test"); 
        MyRequestWrapper flowRequestWrapper= getMyRequestWrapper();
        List<Map<String, Object>> maps = string2List(objectMapper1, flowRequestWrapper.getBody().toString());
        Map<String,Object> map = new HashMap<String, Object>();
        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); 
    }

Please help, Thanks请帮忙,谢谢

Your method is way too complex to be unit tested.您的方法太复杂,无法进行单元测试。 For example it declares dependencies by calling methods in the same class.例如,它通过调用同一类中的方法来声明依赖关系。 You cannot mock those and it makes the testing many times more complicated.你不能嘲笑那些,它使测试复杂很多倍。

List<Map<String,Object>> recordMaps =
    string2List(objectMapper,requestWrapper.getBody().toString());

You need to extract the string2List method into a standalone class (with it's own unit tests) that is injected into your class as a dependency.您需要将string2List方法提取到作为依赖项注入到您的类中的独立类(带有它自己的单元测试)中。

Then you can just mock the string2List class and when you do that, you control the creation of recordObj instances from your unit test for this method.然后你可以模拟string2List类,当你这样做时,你可以从你的单元测试中为这个方法控制recordObj实例的创建。

Your second "sin" is abusing lambdas by creating one that is longer than two lines.你的第二个“罪”是通过创建一个超过两行的 lambda 来滥用 lambda。 Lambdas should be short. Lambda 应该很短。 If it spans more than a few lines, it must be extracted into a standalone class that can be unit tested separately.如果它跨越多行,则必须将其提取到可以单独进行单元测试的独立类中。 And again, when you have extracted this lambda into a standalone class and unit tested it, you can't just go " new RecordObjConsumer(results) " in your method, as that creates a hard-coded dependency that you again cannot mock.同样,当您将这个 lambda 提取到一个独立的类并对其进行单元测试时,您不能只在您的方法中使用“ new RecordObjConsumer(results) ”,因为这会创建一个您再次无法模拟的硬编码依赖项。 You need to design the consumer so that it can be injected into your class as an external dependency.您需要设计使用者,以便它可以作为外部依赖项注入到您的类中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM