You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含Lambda表达式的myFunction编写单元测试验证全列表执行

验证myFunction完整遍历列表的单元测试方案

原代码

public static void myFunction() {
    List<Integer> list = Arrays.asList(1,2,3,4,5,6);
    list.forEach(num -> {
        checkNumber(num);
    });
}

public static void checkNumber(Integer num) throws RuntimeException {
    try {
        if(num.equals(3))
            throw new RuntimeException("3 found not to execute");
        System.out.println("mynum:"+num);
    }
    catch (Exception e) {
        System.out.println(e);
    }
}

核心测试思路

要验证myFunction遍历完整列表,关键是记录每个元素的处理痕迹,确保所有元素(包括触发异常的3)都被checkNumber执行过。以下是两种可行方案:


方案1:重构代码提升可测试性(推荐)

原代码依赖控制台输出,不利于测试。通过抽象输出逻辑,解耦依赖后可以用Mock工具验证每个元素的处理情况:

  1. 定义输出接口
public interface OutputHandler {
    void printNumber(String message);
    void printException(Exception e);
}
  1. 修改原类,注入输出逻辑
public class MyClass {
    private OutputHandler outputHandler;

    // 测试用构造方法
    public MyClass(OutputHandler outputHandler) {
        this.outputHandler = outputHandler;
    }

    // 兼容原有调用的无参构造
    public MyClass() {
        this.outputHandler = new ConsoleOutputHandler();
    }

    public void myFunction() {
        List<Integer> list = Arrays.asList(1,2,3,4,5,6);
        list.forEach(this::checkNumber);
    }

    public void checkNumber(Integer num) throws RuntimeException {
        try {
            if(num.equals(3))
                throw new RuntimeException("3 found not to execute");
            outputHandler.printNumber("mynum:"+num);
        } catch (Exception e) {
            outputHandler.printException(e);
        }
    }

    // 默认控制台输出实现
    private static class ConsoleOutputHandler implements OutputHandler {
        @Override
        public void printNumber(String message) {
            System.out.println(message);
        }

        @Override
        public void printException(Exception e) {
            System.out.println(e);
        }
    }
}
  1. 编写JUnit+Mockito测试用例
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.util.Arrays;

import static org.mockito.Mockito.verify;

public class MyClassTest {
    @Test
    void myFunction_processesAllNumbers() {
        OutputHandler mockHandler = Mockito.mock(OutputHandler.class);
        MyClass myClass = new MyClass(mockHandler);

        myClass.myFunction();

        // 验证正常数字的输出调用
        for (Integer num : Arrays.asList(1,2,4,5,6)) {
            verify(mockHandler).printNumber("mynum:" + num);
        }
        // 验证异常数字的异常处理调用
        verify(mockHandler).printException(Mockito.argThat(e ->
            e instanceof RuntimeException && e.getMessage().equals("3 found not to execute")
        ));
    }
}

方案2:不重构,拦截控制台输出(适合遗留代码)

如果无法修改原代码,可以通过拦截System.out收集输出,验证所有元素的处理痕迹:

import org.junit.jupiter.api.Test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class MyClassTest {
    @Test
    void myFunction_processesAllNumbers() {
        PrintStream originalOut = System.out;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        System.setOut(new PrintStream(baos));

        try {
            MyClass.myFunction();
            String output = baos.toString();

            List<Integer> allNumbers = Arrays.asList(1,2,3,4,5,6);
            for (Integer num : allNumbers) {
                if (num == 3) {
                    assertTrue(output.contains("3 found not to execute"));
                } else {
                    assertTrue(output.contains("mynum:" + num));
                }
            }
        } finally {
            System.setOut(originalOut);
        }
    }
}

内容的提问来源于stack exchange,提问作者user404

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:55:27