讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在JUnit测试中正确处理被@NotNull标记但需验证空值的字段

轻强君_2865

轻强君_2865

发布时间:2026-05-09 17:21:38

|

850人浏览过

|

来源于php中文网

原创

如何在JUnit测试中正确处理被@NotNull标记但需验证空值的字段

本文讲解当Java Bean字段被@NotNull等JSR-303校验注解约束时,如何在JUnit单元测试中安全模拟null输入以验证参数校验逻辑,避免因构造阶段触发非预期的NullPointerException。

本文讲解当java bean字段被`@notnull`等jsr-303校验注解约束时,如何在junit单元测试中安全模拟`null`输入以验证参数校验逻辑,避免因构造阶段触发非预期的`nullpointerexception`。

在Spring或Jakarta EE项目中,使用@NotNull、@NotEmpty等校验注解(来自jakarta.validation或旧版javax.validation)是一种常见做法,用于声明字段的业务约束。然而,这些注解本身不会自动拦截赋值操作——它们仅在显式调用校验器(如Validator.validate())时生效。你遇到的错误:

java.lang.NullPointerException: endDate is marked non-null but is null

并非由@NotNull触发,而是由Lombok的@Setter生成的 setter 方法内部的隐式空值检查导致的。Lombok自2.0+版本起默认启用@NonNull语义支持:当字段被@NotNull(或同名注解)标注时,Lombok会为对应setter自动生成非空断言(即类似 if (endDate == null) throw new NullPointerException("endDate is marked non-null but is null"))。这是Lombok的主动防护行为,与JSR-303校验无关。

✅ 正确的修复方式

要让测试能传入null值并交由你的业务逻辑(如@Valid控制器校验)统一处理,必须禁用Lombok对@NotNull的setter空值拦截。推荐两种方案:

方案1:移除Lombok的@NotNull依赖(推荐)

将字段上的@NotNull替换为纯校验注解(不参与Lombok代码生成),例如使用jakarta.validation.constraints.NotBlank(适用于字符串)或@NotNull但确保其来源是jakarta.validation.constraints而非Lombok感知的注解,并显式关闭Lombok的@NonNull推导:

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.List;

@Getter
@Setter
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartDataSearchCondition {
    @NotBlank(message = "startDate must not be blank")
    @Pattern(regexp = Constants.REGEX_CHART_CONDITION_DATE, message = "startDate format invalid")
    private String startDate;

    @NotBlank(message = "endDate must not be blank")
    @Pattern(regexp = Constants.REGEX_CHART_CONDITION_DATE, message = "endDate format invalid")
    private String endDate;

    @NotNull(message = "columns must not be null")
    @NotEmpty(message = "columns must not be empty")
    private List<String> columns;
}

并在lombok.config文件中添加(防止Lombok误判):

lombok.anyConstructor.addConstructorProperties = false
lombok.setter.flagUsage = WARNING  // 或 ERROR,避免误用
# 关键:禁用Lombok对jakarta.validation注解的setter空检查
lombok.nonNull.failOnNull = false

方案2:手动编写setter(完全可控)

若需彻底规避Lombok干预,可移除@Setter,手写setter方法,跳过空值检查:

public void setEndDate(String endDate) {
    this.endDate = endDate; // 不做null检查,交由后续校验器处理
}

方案3:测试时绕过setter(快速临时解法)

在测试中直接通过反射或构造器初始化对象(不调用setter):

@Test
public void visualize_searchConditionWithEndDateIsNull() {
    List<String> columns = List.of("col2");

    // 使用反射绕过Lombok生成的带空检查的setter
    ChartDataSearchCondition condition = new ChartDataSearchCondition();
    try {
        Field endDateField = condition.getClass().getDeclaredField("endDate");
        endDateField.setAccessible(true);
        endDateField.set(condition, null); // 强制设为null

        Field startDateField = condition.getClass().getDeclaredField("startDate");
        startDateField.setAccessible(true);
        startDateField.set(condition, "2021-06-01 19:00:00.000+0700");

        Field columnsField = condition.getClass().getDeclaredField("columns");
        columnsField.setAccessible(true);
        columnsField.set(condition, columns);

        // 调用目标方法(此时endDate为null,等待@Valid触发校验)
        controller.getTimeseriesSampling(cluster, database, container, condition);
        Assert.fail("Expected validation exception");
    } catch (Exception e) {
        // 预期捕获校验失败异常
        if (e instanceof CommonException ce && 
            ErrorCode.CHART_REQUEST_INVALID.getErrorCode().equals(ce.getCode())) {
            return;
        }
        throw e;
    }
}

⚠️ 注意:反射方式仅建议用于紧急验证,长期应采用方案1或2以保持代码清晰与可维护性。

✅ 最佳实践总结

  • ✅ @NotNull等校验注解应仅用于声明式校验,不应承担运行时空值防护职责;
  • ✅ Lombok的@Setter + @NotNull组合易引发混淆,建议分离关注点:Lombok负责便捷访问,jakarta.validation负责业务校验;
  • ✅ 单元测试中验证null场景时,确保对象构建过程不提前抛出异常,把校验时机留给@Valid或显式validator.validate()调用;
  • ✅ Spring MVC控制器中,务必配合@Valid或@Validated使用,才能真正触发JSR-303校验逻辑并返回MethodArgumentNotValidException或自定义异常。

通过以上调整,你的测试即可成功传入null值,并由业务层统一捕获和响应校验失败,既符合契约设计,也保障了测试完整性。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

相关专题

更多
软件测试常用工具
软件测试常用工具

软件测试常用工具有Selenium、JUnit、Appium、JMeter、LoadRunner、Postman、TestNG、LoadUI、SoapUI、Cucumber和Robot Framework等等。测试人员可以根据具体的测试需求和技术栈选择适合的工具,提高测试效率和准确性 。

4630

2023.10.13

java测试工具有哪些
java测试工具有哪些

java测试工具有JUnit、TestNG、Mockito、Selenium、Apache JMeter和Cucumber。php还给大家带来了java有关的教程,欢迎大家前来学习阅读,希望对大家能有所帮助。

3021

2023.10.23

Java 单元测试
Java 单元测试

本专题聚焦 Java 在软件测试与持续集成流程中的实战应用,系统讲解 JUnit 单元测试框架、Mock 数据、集成测试、代码覆盖率分析、Maven 测试配置、CI/CD 流水线搭建(Jenkins、GitHub Actions)等关键内容。通过实战案例(如企业级项目自动化测试、持续交付流程搭建),帮助学习者掌握 Java 项目质量保障与自动化交付的完整体系。

1086

2025.10.24

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

60

2026.10.16

OpenJDK怎么配置Java开发环境
OpenJDK怎么配置Java开发环境

怎样用OpenJDK搭建开发环境?本专题介绍版本选择、下载安装、环境变量配置和编译运行验证,帮助你理清JDK的作用及基本配置流程,并通过简单程序检查环境是否可用,为后续项目开发做好准备。

40

2026.10.16

OpenJDK怎么部署Java应用
OpenJDK怎么部署Java应用

Java项目开发完成后,怎样部署到目标环境并正常运行?本专题介绍OpenJDK应用部署流程,涵盖运行环境准备、版本兼容检查、应用打包、启动参数配置和日志查看,帮助你理清部署前后的操作顺序,减少环境差异造成的运行问题。

40

2026.10.16

Revel框架模板渲染与表单验证
Revel框架模板渲染与表单验证

本专题围绕Revel框架视图层开发,介绍模板语法、变量输出、布局复用、表单提交、参数绑定与验证规则,帮助开发者完成安全规范的页面交互。

20

2026.10.16

Revel框架MVC路由与控制器
Revel框架MVC路由与控制器

本专题聚焦Revel框架MVC核心机制,讲解路由定义、控制器Action、参数绑定、请求响应和反向路由,并结合常见场景梳理接口请求处理流程。

20

2026.10.16

Revel框架入门与安装配置
Revel框架入门与安装配置

本专题从Revel框架环境搭建讲起,系统介绍命令行工具安装、项目创建、目录结构、配置文件及热代码重载,帮助开发者快速完成首个Go Web应用。

20

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn