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

使用JUnit/Mockito测试遗留代码时的HandlerException模拟问题

测试抛出HandlerException的静态方法方案

嘿,针对你遇到的这个测试静态方法抛出自定义异常的问题,我给你整理了几个实用的方案,都是实际项目里常用的:

核心思路

我们的目标很明确:验证当传入的JsonElement不包含ID_TAG时,parse方法确实抛出了预期的HandlerException,并且异常信息和代码里定义的一致。因为这个方法是静态的,而且没有复杂的外部依赖,其实不用Mockito也能轻松搞定,先从最简单的方案说起。

JUnit 5 直接测试方案(最常用)

如果你的项目用的是JUnit 5(现在主流都是这个版本),可以用assertThrows方法直接捕获并验证异常:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

// 替换成你实际的测试类名
class RecordParserTest {
    // 替换成你代码里实际的ID_TAG值
    private static final String ID_TAG = "id";

    @Test
    void parse_WhenRecordMissingId_ThrowsHandlerException() {
        // 1. 构造不包含ID_TAG的测试数据
        JsonObject emptyRecord = new JsonObject();
        JsonElement record = emptyRecord;

        // 2. 执行方法并捕获异常
        HandlerException thrownException = assertThrows(HandlerException.class, () -> {
            // 替换成你实际的静态方法所在类
            RecordParser.parse(record);
        });

        // 3. 验证异常信息是否符合预期
        assertEquals("Failed to find Id ...", thrownException.getMessage());
    }
}

这个方案的好处是简洁直观,assertThrows会自动检查lambda里的代码是否抛出了指定类型的异常,如果没抛出或者抛出了其他类型,测试直接失败。

JUnit 4 兼容方案

如果你的遗留项目还在使用JUnit 4,也有两种方式来测试异常:

方式1:直接指定预期异常

这种方式简单,但没法验证异常信息:

import org.junit.Test;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class RecordParserTest {
    private static final String ID_TAG = "id";

    @Test(expected = HandlerException.class)
    public void parse_WhenRecordMissingId_ThrowsHandlerException() throws HandlerException {
        JsonObject emptyRecord = new JsonObject();
        JsonElement record = emptyRecord;
        RecordParser.parse(record);
    }
}

方式2:用ExpectedException规则验证异常信息

如果需要验证异常内容,就得用JUnit 4的规则类:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class RecordParserTest {
    private static final String ID_TAG = "id";

    @Rule
    public ExpectedException exceptionRule = ExpectedException.none();

    @Test
    public void parse_WhenRecordMissingId_ThrowsHandlerExceptionWithCorrectMessage() {
        // 先声明预期的异常类型和信息
        exceptionRule.expect(HandlerException.class);
        exceptionRule.expectMessage("Failed to find Id ...");

        // 执行测试方法
        JsonObject emptyRecord = new JsonObject();
        JsonElement record = emptyRecord;
        RecordParser.parse(record);
    }
}

有静态依赖时的Mockito Mock方案

如果你的parse方法里还有其他静态依赖(比如调用了其他静态工具类的方法),这时候才需要用到Mockito的静态Mock功能。比如假设你的方法是这样的:

public static void parse(JsonElement record) throws HandlerException {
    JsonElement element = record.getAsJsonObject().get(ID_TAG);
    if(element == null) {
        throw new HandlerException("Failed to find Id ...");
    }
    // 假设有一个静态方法调用
    StaticDataProcessor.process(element);
}

测试抛出异常的分支时,我们需要确保静态依赖不会被执行,这时候可以用Mockito的mockStatic:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

class RecordParserTest {
    private static final String ID_TAG = "id";

    @Test
    void parse_WhenRecordMissingId_ThrowsHandlerException() {
        JsonObject emptyRecord = new JsonObject();
        JsonElement record = emptyRecord;

        // 用try-with-resources包裹静态Mock,自动关闭避免影响其他测试
        try (MockedStatic<StaticDataProcessor> mockedStatic = mockStatic(StaticDataProcessor.class)) {
            HandlerException thrownException = assertThrows(HandlerException.class, () -> {
                RecordParser.parse(record);
            });

            assertEquals("Failed to find Id ...", thrownException.getMessage());
            // 验证静态方法没有被调用(因为我们走的是抛出异常的分支)
            mockedStatic.verify(() -> StaticDataProcessor.process(any(JsonElement.class)), never());
        }
    }
}

注意:静态Mock尽量少用,因为它会修改类的静态状态,如果处理不好容易导致测试之间的污染,能用普通测试方案解决的就别用静态Mock。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:47:15