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

如何用JUnit测试Jackson JsonAnySetter注解的调用情况?

如何测试Jackson @JsonAnySetter处理未定义属性的日志功能

这个问题很实用!要验证你的Book类中@JsonAnySetter的日志记录逻辑,我们可以结合JUnit 5、Jackson的ObjectMapper,再配合日志捕获工具来确认未定义属性是否触发了预期的警告日志。下面给你两种常用的测试方案:

方案一:使用slf4j-test直接捕获日志

slf4j-test是SLF4J官方提供的测试库,可以方便地捕获和验证日志输出,不需要额外的mock操作。

步骤1:添加依赖(以Maven为例)

在你的pom.xml中加入slf4j-test依赖:

<dependency>
    <groupId>uk.org.lidalia</groupId>
    <artifactId>slf4j-test</artifactId>
    <version>1.2.0</version>
    <scope>test</scope>
</dependency>

步骤2:编写测试用例

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import uk.org.lidalia.slf4jtest.TestLogger;
import uk.org.lidalia.slf4jtest.TestLoggerFactory;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static uk.org.lidalia.slf4jtest.LoggingEvent.warn;

class BookTest {

    // 初始化Jackson的ObjectMapper
    private final ObjectMapper objectMapper = new ObjectMapper();
    // 获取Book类对应的测试日志实例
    private final TestLogger testLogger = TestLoggerFactory.getTestLogger(Book.class);

    @Test
    void shouldLogWarningForUndefinedProperties() throws Exception {
        // 准备包含未定义属性的JSON数据
        String jsonWithUnknownFields = """
                {
                    "titleId": "BK-001",
                    "bookName": "Effective Java",
                    "authors": ["Joshua Bloch"],
                    "publisher": "Addison-Wesley",
                    "publicationYear": 2008
                }
                """;

        // 执行反序列化操作
        Book book = objectMapper.readValue(jsonWithUnknownFields, Book.class);

        // 先验证已知属性是否正确反序列化(确保基础功能正常)
        assertEquals("BK-001", book.getTitleId());
        assertEquals("Effective Java", book.getBookName());
        assertEquals(List.of("Joshua Bloch"), book.getAuthors());

        // 验证未定义属性是否触发了警告日志
        assertTrue(testLogger.contains(warn("Received a key which hasn't been mapped. Key: publisher, Value: Addison-Wesley")));
        assertTrue(testLogger.contains(warn("Received a key which hasn't been mapped. Key: publicationYear, Value: 2008")));
    }
}

方案二:使用Mockito验证日志输出

如果你已经在项目中使用Mockito,也可以通过mock日志对象来验证警告是否被调用。需要注意的是,由于@Slf4j生成的是private static final类型的日志对象,我们需要通过反射来替换它。

步骤1:编写测试用例

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class BookTestWithMockito {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void shouldTriggerWarningLogForUnknownProperties() throws Exception {
        // 创建mock的Logger对象
        Logger mockLog = mock(Logger.class);

        // 通过反射替换Book类中的静态log字段
        Field logField = Book.class.getDeclaredField("log");
        logField.setAccessible(true);
        logField.set(null, mockLog); // 静态字段传入null作为实例参数

        // 准备测试用的JSON数据
        String jsonWithUnknownFields = """
                {
                    "titleId": "BK-002",
                    "bookName": "Clean Code",
                    "authors": ["Robert C. Martin"],
                    "pages": 464
                }
                """;

        // 执行反序列化
        Book book = objectMapper.readValue(jsonWithUnknownFields, Book.class);

        // 验证已知属性反序列化正确
        assertEquals("BK-002", book.getTitleId());
        assertEquals("Clean Code", book.getBookName());
        assertEquals(List.of("Robert C. Martin"), book.getAuthors());

        // 验证警告日志是否被调用
        verify(mockLog).warn("Received a key which hasn't been mapped. Key: {}, Value: {}", "pages", 464);
    }
}

额外注意事项

  1. 由于你的Book类使用了@Value和@Builder,确保Jackson能正确处理不可变类的反序列化。如果遇到反序列化失败的问题,可以添加jackson-module-parameter-names依赖,并确保ObjectMapper启用了参数名称模块。
  2. 测试时尽量覆盖多种类型的未定义属性(比如字符串、数字、数组等),确保@JsonAnySetter能处理不同类型的value参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:04:21