apache-common

实用Java工具类详解
本文详细介绍了Java开发中常用的工具类,如ArrayUtils、StringUtils、DateUtils等,并对其功能进行了说明,包括数组操作、字符串处理、日期时间管理等方面。

 

 

 

 

 

 

 

 

 

 

common-lang (2.1)
ArrayUtils
常量中包含了基本类型(及其相对应类)的空数组。
提供向数组增加元素(包括增加单个元素或是整个数组),删除元素,翻转元素排列次序
克隆数组(基本类型)
查找数组中的元素(是否包含,返回索引)
获得数组长度( null 安全,返回为 0
数组是否为空,数组是否相等,长度是否相等,元素类型是否相同,
基本类型对应类数组转换成基本类型数组
转成字符串
BooleanUtils
Boolean 的转换(可转成 int String
 
CharUtils
针对 Char 的工具类包括判断是不是 ASCII 字符,是不是控制符可打印与否,转成整形
ClassUtils
获得包名,获得类的所有超类。
RandomStringUtils
随机字符串生成,可生成数字串,也可生成 Ascii 范围的字串
StringEscapeUtils
编码 / 解码 针对 xml/html/sql/javascript/java( 主要是转义标记符号等 )
StringUtils
String 的增强。类似 vb 的函数。截断、查找、替换、判断空、大小写、合并、分割,反写,对比
SerializationUtils
序列化工具类,将类转序列或反序列
SystemUtils
系统工具类,判断 JRE 版本,判断操作系统,判断字体 (AWT) ,获得 JAVA_HOME (及相关的所有环境变量),操作系统版本,时区、当前用户名,获得用户文件夹
Validate
校验器,判断集合里面所有的对象是否是某类,判断集合里面所有对象都非空,判断集合是否为空,判断数组、 Map 或字符串是否为空
WordUtils
将一个字符串中的单词首字大写;根据提供的每行字数将一个字符串断行
ToStringBuilder
toString 方法的增强类 , 可将对象转成字符串 ( 除了打出引用地址还会打出所有属性 ) 可设置显示的风格 (ToStringStyle, 抽象类 , 需继承实现后方可使用 )
EqualsBuilder
相等判断 , 例如以下语句 :
a = b == c
a = a && e == f
可转换成
a = new EqualsBuilder()
.append( b,c )
.append( e,f)
.isEquals();
HashCodeBuilder
获得哈希值
Enum
枚举型 , 看来会被 5.0 替代 .
ExceptionUtils
对异常的常见操作 , 获得堆栈 , 异常抛出方法名 , 错误链中对象数 ( 要这个干吗 ???)
RandomUtils
随机数据生成类 , 包括浮点 , 双精 , 布尔 , 整形 , 长整在内的随机数生成
NumberUtils
常用数字函数 , 最大值 , 最小值 , 字符串和数值转换
DateFormatUtils
格式化日期时间 , 支持默认格式 ( 即常量格式 ) 如下 :
ISO8601 ( 包含时区和不包含时区 )
SMTP 数据头格式
DateUtils
日期工具类 , 对比日期 , 削去部分数据 , 没啥用
FastDateFormat
SimpleDateFormat 的线程安全版本 , 听说速度更快
StopWatch
秒表 , 监控运行时间的常用工具 .
common-beanutils (1.7)
BeanUtils
克隆一个对象甚至他自身并未实现克隆方法
复制一个对象的属性至另一个对象
复制一个对象的指定属性至另一个对象
将一个对象的所有属性都到一个 Map
获得一个对象的一个数组属性
直接访问对象的 Map 类型的属性中的元素
将一个 Map 对象的键值复制到目标对象的相应属性
ConstructorUtils
从一个类获得其构造器
DynaBean
动态 Bean
Validator 1.1.4
看样子是从 Struts 里面剥离出来的,用用其工具类就 OK 了。其他的太繁琐。
CreditCardValidator
信用卡校验
DateValidator
日期校验,可根据给的日期模板( SimpleDateFormat )校验
EmailValidator
校验电子邮件,可以校验域名、用户名
GenericTypeValidator
将字符串转换成 Int/Double/Float/Long/Date/Byte
GenericValidator
常用校验器(静态方法),包括:字符串是否为空或者为 null ,字符串是否为 byte 。是否为信用卡,是否为日期(根据模板),是否为浮点数,是否为电邮,是否为双精数,是否在数值范围(类型:浮点,双精,整,长整,端整,字节),是否为 URL ,是否符合正则表达式,字符串是否超长,数值是否超过指定值,字符串是否过短,数值是否低于指定值
ISBNValidator
ISBN 校验器
UrlValidator
URL 校验器
Validator
校验器(需实例化),和资源文件关联

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2024.3.6\lib\idea_rt.jar=65370" -javaagent:C:\Users\admin\AppData\Local\JetBrains\IntelliJIdea2024.3\captureAgent\debugger-agent.jar -Dkotlinx.coroutines.debug.enable.creation.stack.trace=false -Ddebugger.agent.enable.coroutines=true -Dkotlinx.coroutines.debug.enable.flows.stack.trace=true -Dkotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace=true -Dfile.encoding=UTF-8 -classpath "D:\Program Files\JetBrains\IntelliJ IDEA 2024.3.6\lib\idea_rt.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2024.3.6\plugins\junit\lib\junit5-rt.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2024.3.6\plugins\junit\lib\junit-rt.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\charsets.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\access-bridge-64.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\cldrdata.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\dnsns.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\jaccess.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\jfxrt.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\localedata.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\nashorn.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\sunec.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\sunjce_provider.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\sunmscapi.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\sunpkcs11.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\ext\zipfs.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\jce.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\jfr.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\jfxswt.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\jsse.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\management-agent.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\resources.jar;D:\java\openlogic-openjdk-8u362-b09-windows-64\openlogic-openjdk-8u362-b09-windows-64\jre\lib\rt.jar;F:\lee\work\training-2025\litailong\basic-spring-boot\target\test-classes;F:\lee\work\training-2025\litailong\basic-spring-boot\target\classes;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-validation\2.7.18\spring-boot-starter-validation-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter\2.7.18\spring-boot-starter-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot\2.7.18\spring-boot-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-autoconfigure\2.7.18\spring-boot-autoconfigure-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-logging\2.7.18\spring-boot-starter-logging-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\ch\qos\logback\logback-classic\1.2.12\logback-classic-1.2.12.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\ch\qos\logback\logback-core\1.2.12\logback-core-1.2.12.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\yaml\snakeyaml\1.30\snakeyaml-1.30.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.83\tomcat-embed-el-9.0.83.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\hibernate\validator\hibernate-validator\6.2.5.Final\hibernate-validator-6.2.5.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\jboss\logging\jboss-logging\3.4.3.Final\jboss-logging-3.4.3.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-web\2.7.18\spring-boot-starter-web-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-json\2.7.18\spring-boot-starter-json-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.5\jackson-datatype-jdk8-2.13.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.5\jackson-datatype-jsr310-2.13.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.5\jackson-module-parameter-names-2.13.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-tomcat\2.7.18\spring-boot-starter-tomcat-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.83\tomcat-embed-core-9.0.83.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.83\tomcat-embed-websocket-9.0.83.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-web\5.3.31\spring-web-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-beans\5.3.31\spring-beans-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-webmvc\5.3.31\spring-webmvc-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-context\5.3.31\spring-context-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-expression\5.3.31\spring-expression-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-aop\2.7.18\spring-boot-starter-aop-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-aop\5.3.31\spring-aop-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\aspectj\aspectjweaver\1.9.7\aspectjweaver-1.9.7.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\projectlombok\lombok\1.18.30\lombok-1.18.30.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-test\2.7.18\spring-boot-starter-test-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-test\2.7.18\spring-boot-test-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.7.18\spring-boot-test-autoconfigure-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\jayway\jsonpath\json-path\2.7.0\json-path-2.7.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\minidev\json-smart\2.4.11\json-smart-2.4.11.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\minidev\accessors-smart\2.4.11\accessors-smart-2.4.11.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\ow2\asm\asm\9.3\asm-9.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\assertj\assertj-core\3.22.0\assertj-core-3.22.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\junit\jupiter\junit-jupiter\5.8.2\junit-jupiter-5.8.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\junit\jupiter\junit-jupiter-api\5.8.2\junit-jupiter-api-5.8.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\junit\platform\junit-platform-commons\1.8.2\junit-platform-commons-1.8.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\junit\jupiter\junit-jupiter-params\5.8.2\junit-jupiter-params-5.8.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\junit\jupiter\junit-jupiter-engine\5.8.2\junit-jupiter-engine-5.8.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\junit\platform\junit-platform-engine\1.8.2\junit-platform-engine-1.8.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\mockito\mockito-core\4.5.1\mockito-core-4.5.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\bytebuddy\byte-buddy\1.12.23\byte-buddy-1.12.23.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\bytebuddy\byte-buddy-agent\1.12.23\byte-buddy-agent-1.12.23.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\objenesis\objenesis\3.2\objenesis-3.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\mockito\mockito-junit-jupiter\4.5.1\mockito-junit-jupiter-4.5.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\skyscreamer\jsonassert\1.5.1\jsonassert-1.5.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-core\5.3.31\spring-core-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-jcl\5.3.31\spring-jcl-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-test\5.3.31\spring-test-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\xmlunit\xmlunit-core\2.9.1\xmlunit-core-2.9.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-data-jpa\2.7.18\spring-boot-starter-data-jpa-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-jdbc\2.7.18\spring-boot-starter-jdbc-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\zaxxer\HikariCP\4.0.3\HikariCP-4.0.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-jdbc\5.3.31\spring-jdbc-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\hibernate\hibernate-core\5.6.15.Final\hibernate-core-5.6.15.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\jboss\jandex\2.4.2.Final\jandex-2.4.2.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\hibernate\common\hibernate-commons-annotations\5.1.2.Final\hibernate-commons-annotations-5.1.2.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\glassfish\jaxb\jaxb-runtime\2.3.9\jaxb-runtime-2.3.9.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\glassfish\jaxb\txw2\2.3.9\txw2-2.3.9.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\sun\istack\istack-commons-runtime\3.0.12\istack-commons-runtime-3.0.12.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\sun\activation\jakarta.activation\1.2.2\jakarta.activation-1.2.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\data\spring-data-jpa\2.7.18\spring-data-jpa-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\data\spring-data-commons\2.7.18\spring-data-commons-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-orm\5.3.31\spring-orm-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-aspects\5.3.31\spring-aspects-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\mysql\mysql-connector-j\8.0.33\mysql-connector-j-8.0.33.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-actuator\2.7.18\spring-boot-starter-actuator-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-actuator-autoconfigure\2.7.18\spring-boot-actuator-autoconfigure-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-actuator\2.7.18\spring-boot-actuator-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\micrometer\micrometer-core\1.11.5\micrometer-core-1.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\micrometer\micrometer-commons\1.11.5\micrometer-commons-1.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\micrometer\micrometer-observation\1.11.5\micrometer-observation-1.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\hdrhistogram\HdrHistogram\2.1.12\HdrHistogram-2.1.12.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\latencyutils\LatencyUtils\2.0.3\LatencyUtils-2.0.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\micrometer\micrometer-registry-prometheus\1.11.5\micrometer-registry-prometheus-1.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\prometheus\simpleclient_common\0.15.0\simpleclient_common-0.15.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\prometheus\simpleclient\0.15.0\simpleclient-0.15.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\prometheus\simpleclient_tracer_otel\0.15.0\simpleclient_tracer_otel-0.15.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\prometheus\simpleclient_tracer_common\0.15.0\simpleclient_tracer_common-0.15.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\prometheus\simpleclient_tracer_otel_agent\0.15.0\simpleclient_tracer_otel_agent-0.15.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\jsonwebtoken\jjwt-api\0.11.5\jjwt-api-0.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\jsonwebtoken\jjwt-impl\0.11.5\jjwt-impl-0.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\jsonwebtoken\jjwt-jackson\0.11.5\jjwt-jackson-0.11.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\jackson\core\jackson-databind\2.13.5\jackson-databind-2.13.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.5\jackson-annotations-2.13.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\fasterxml\jackson\core\jackson-core\2.13.5\jackson-core-2.13.5.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-netty-shaded\1.56.1\grpc-netty-shaded-1.56.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\guava\guava\31.1-android\guava-31.1-android.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\checkerframework\checker-qual\3.12.0\checker-qual-3.12.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\errorprone\error_prone_annotations\2.18.0\error_prone_annotations-2.18.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\perfmark\perfmark-api\0.26.0\perfmark-api-0.26.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-protobuf\1.56.1\grpc-protobuf-1.56.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\api\grpc\proto-google-common-protos\2.17.0\proto-google-common-protos-2.17.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-protobuf-lite\1.56.1\grpc-protobuf-lite-1.56.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-stub\1.56.1\grpc-stub-1.56.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\protobuf\protobuf-java\3.23.4\protobuf-java-3.23.4.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\devh\grpc-spring-boot-starter\2.14.0.RELEASE\grpc-spring-boot-starter-2.14.0.RELEASE.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\devh\grpc-server-spring-boot-starter\2.14.0.RELEASE\grpc-server-spring-boot-starter-2.14.0.RELEASE.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\devh\grpc-server-spring-boot-autoconfigure\2.14.0.RELEASE\grpc-server-spring-boot-autoconfigure-2.14.0.RELEASE.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\devh\grpc-common-spring-boot\2.14.0.RELEASE\grpc-common-spring-boot-2.14.0.RELEASE.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-core\1.51.0\grpc-core-1.51.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\code\gson\gson\2.9.1\gson-2.9.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\android\annotations\4.1.1.4\annotations-4.1.1.4.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\codehaus\mojo\animal-sniffer-annotations\1.21\animal-sniffer-annotations-1.21.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-services\1.51.0\grpc-services-1.51.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\google\protobuf\protobuf-java-util\3.21.7\protobuf-java-util-3.21.7.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-api\1.51.0\grpc-api-1.51.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\grpc\grpc-context\1.51.0\grpc-context-1.51.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\devh\grpc-client-spring-boot-starter\2.14.0.RELEASE\grpc-client-spring-boot-starter-2.14.0.RELEASE.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\net\devh\grpc-client-spring-boot-autoconfigure\2.14.0.RELEASE\grpc-client-spring-boot-autoconfigure-2.14.0.RELEASE.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\junit\junit\4.13.2\junit-4.13.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\hamcrest\hamcrest-core\2.2\hamcrest-core-2.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-data-cassandra\2.7.18\spring-boot-starter-data-cassandra-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\spring-tx\5.3.31\spring-tx-5.3.31.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\data\spring-data-cassandra\3.4.18\spring-data-cassandra-3.4.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\datastax\oss\java-driver-core\4.14.1\java-driver-core-4.14.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\datastax\oss\native-protocol\1.5.1\native-protocol-1.5.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-handler\4.1.101.Final\netty-handler-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-common\4.1.101.Final\netty-common-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-resolver\4.1.101.Final\netty-resolver-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-buffer\4.1.101.Final\netty-buffer-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-transport\4.1.101.Final\netty-transport-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-transport-native-unix-common\4.1.101.Final\netty-transport-native-unix-common-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\netty\netty-codec\4.1.101.Final\netty-codec-4.1.101.Final.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\datastax\oss\java-driver-shaded-guava\25.1-jre-graal-sub-1\java-driver-shaded-guava-25.1-jre-graal-sub-1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\typesafe\config\1.4.1\config-1.4.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jnr-posix\3.1.15\jnr-posix-3.1.15.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jnr-ffi\2.2.11\jnr-ffi-2.2.11.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jffi\1.3.9\jffi-1.3.9.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jffi\1.3.9\jffi-1.3.9-native.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\ow2\asm\asm-commons\9.2\asm-commons-9.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\ow2\asm\asm-analysis\9.2\asm-analysis-9.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\ow2\asm\asm-tree\9.2\asm-tree-9.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\ow2\asm\asm-util\9.2\asm-util-9.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jnr-a64asm\1.0.0\jnr-a64asm-1.0.0.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jnr-x86asm\1.0.2\jnr-x86asm-1.0.2.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\jnr\jnr-constants\0.10.3\jnr-constants-0.10.3.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\io\dropwizard\metrics\metrics-core\4.2.22\metrics-core-4.2.22.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\reactivestreams\reactive-streams\1.0.4\reactive-streams-1.0.4.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\stephenc\jcip\jcip-annotations\1.0-1\jcip-annotations-1.0-1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\github\spotbugs\spotbugs-annotations\3.1.12\spotbugs-annotations-3.1.12.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\com\datastax\oss\java-driver-query-builder\4.14.1\java-driver-query-builder-4.14.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\boot\spring-boot-starter-data-mongodb\2.7.18\spring-boot-starter-data-mongodb-2.7.18.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\mongodb\mongodb-driver-sync\4.6.1\mongodb-driver-sync-4.6.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\mongodb\bson\4.6.1\bson-4.6.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\mongodb\mongodb-driver-core\4.6.1\mongodb-driver-core-4.6.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\mongodb\bson-record-codec\4.6.1\bson-record-codec-4.6.1.jar;D:\Program Files\apache-maven-3.9.11-bin\apache-maven-3.9.11\repository\org\springframework\data\spring-data-mongodb\3.4.18\spring-data-mongodb-3.4.18.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.tplink.nbu.demo.basicspringboot.service.impl.UserServiceImplTest,testGetUser_CacheHit org.mockito.exceptions.verification.TooManyActualInvocations: userRepository.findById(1L); Wanted 1 time: -> at com.tplink.nbu.demo.basicspringboot.service.impl.UserServiceImplTest.testGetUser_CacheHit(UserServiceImplTest.java:382) But was 2 times: -> at com.tplink.nbu.demo.basicspringboot.service.impl.UserServiceImpl.getUser(UserServiceImpl.java:133) -> at com.tplink.nbu.demo.basicspringboot.service.impl.UserServiceImpl.getUser(UserServiceImpl.java:133) at com.tplink.nbu.demo.basicspringboot.service.impl.UserServiceImplTest.testGetUser_CacheHit(UserServiceImplTest.java:382) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:55) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:100) at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:107) at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:41) at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
最新发布
09-05
这个错误表明你的单元测试中 `userRepository.findById(1L)` 被调用了两次,而你期望它只被调用一次。这通常发生在测试缓存功能时,Mockito 的验证失败,因为 `@Cacheable` 注解在单元测试中**不会自动生效**(除非你额外配置)。 --- ## **问题原因** 1. **`@Cacheable` 在单元测试中不生效**: - Spring 的缓存注解(如 `@Cacheable`)需要 Spring AOP 代理才能工作,而纯单元测试(使用 `MockitoJUnitRunner`)不会创建 Spring 上下文,因此缓存注解会被忽略。 - 即使你的 `UserServiceImpl` 方法上有 `@Cacheable`,Mockito 仍然会直接调用原始方法,而不会触发缓存逻辑。 2. **Mockito 验证失败**: - 你的测试代码期望 `userRepository.findById()` 只被调用一次(因为第二次应该走缓存),但实际上它被调用了两次,因为缓存没有生效。 --- ## **解决方案** ### **方法 1:使用 Spring 的测试支持(推荐)** 改用 `@SpringBootTest` + `@Cacheable` 测试,让 Spring 上下文加载并启用缓存: ```java @RunWith(SpringRunner.class) @SpringBootTest public class UserServiceImplCacheTest { @Autowired private UserService userService; // 由 Spring 注入,支持 AOP 代理 @MockBean private UserRepository userRepository; // Mock 数据库访问 @Test public void testGetUser_CacheHit() { UserDO testUser = new UserDO(); testUser.setId(1L); testUser.setEmail("test@example.com"); // 模拟第一次调用(数据库查询) when(userRepository.findById(1L)).thenReturn(Optional.of(testUser)); // 第一次调用(应访问数据库) UserGetRequestDTO request = new UserGetRequestDTO(); request.setUserId(1L); ResponseResult<UserGetResponseDTO> firstCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 第二次调用(相同参数,应走缓存) ResponseResult<UserGetResponseDTO> secondCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 确保没有再次查询数据库 } } ``` **优点**: - 真实测试 `@Cacheable` 的行为。 - 适用于集成测试或需要 Spring 上下文的场景。 **缺点**: - 测试较慢(需要启动 Spring 上下文)。 --- ### **方法 2:手动模拟缓存(纯单元测试)** 如果你坚持使用 `MockitoJUnitRunner`,可以手动模拟缓存行为: ```java @RunWith(MockitoJUnitRunner.class) public class UserServiceImplTest { @Mock private UserRepository userRepository; @InjectMocks private UserServiceImpl userService; private Map<Long, UserDO> cache = new HashMap<>(); // 手动模拟缓存 @Before public void setUp() { cache.clear(); // 每个测试前清空缓存 } @Test public void testGetUser_CacheHit() { UserDO testUser = new UserDO(); testUser.setId(1L); testUser.setEmail("test@example.com"); // 模拟第一次调用(数据库查询) when(userRepository.findById(1L)).thenReturn(Optional.of(testUser)); // 第一次调用(应访问数据库) UserGetRequestDTO request = new UserGetRequestDTO(); request.setUserId(1L); ResponseResult<UserGetResponseDTO> firstCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 手动缓存结果(模拟 @Cacheable 行为) cache.put(1L, testUser); // 第二次调用(相同参数,应走缓存) // 这里需要修改 UserServiceImpl.getUser(),使其检查缓存(仅用于测试) // 例如: // if (cache.containsKey(requestDTO.getUserId())) { // return ResponseResult.success(UserGetResponseDTO.from(cache.get(requestDTO.getUserId()))); // } ResponseResult<UserGetResponseDTO> secondCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 确保没有再次查询数据库 } } ``` **优点**: - 测试速度快(不依赖 Spring 上下文)。 - 完全控制缓存行为。 **缺点**: - 需要修改 `UserServiceImpl` 代码以支持手动缓存(仅用于测试)。 --- ### **方法 3:使用 Spring CacheTest 工具** Spring 提供了 `CacheTestUtils` 或 `CacheManager` 的 Mock 方式: ```java @RunWith(MockitoJUnitRunner.class) public class UserServiceImplTest { @Mock private UserRepository userRepository; @Mock private CacheManager cacheManager; // Mock CacheManager @InjectMocks private UserServiceImpl userService; @Test public void testGetUser_CacheHit() { UserDO testUser = new UserDO(); testUser.setId(1L); testUser.setEmail("test@example.com"); // 模拟缓存 Cache cache = mock(Cache.class); when(cacheManager.getCache("userCache")).thenReturn(cache); when(cache.get(1L, UserDO.class)).thenReturn(null); // 第一次调用,缓存未命中 // 模拟数据库查询 when(userRepository.findById(1L)).thenReturn(Optional.of(testUser)); // 第一次调用(应访问数据库) UserGetRequestDTO request = new UserGetRequestDTO(); request.setUserId(1L); ResponseResult<UserGetResponseDTO> firstCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 模拟缓存已存在 when(cache.get(1L, UserDO.class)).thenReturn(testUser); // 第二次调用(应走缓存) ResponseResult<UserGetResponseDTO> secondCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 确保没有再次查询数据库 } } ``` **优点**: - 比手动模拟缓存更接近真实行为。 - 适用于测试缓存逻辑但不启动完整 Spring 上下文。 **缺点**: - 仍然需要 Mock `CacheManager`,可能不够直观。 --- ## **推荐方案** - **如果测试缓存是核心需求** → 使用 **方法 1(`@SpringBootTest`)**,因为 `@Cacheable` 需要 Spring AOP 代理。 - **如果追求测试速度** → 使用 **方法 2(手动模拟缓存)**,但需要调整代码。 - **折中方案** → 使用 **方法 3(Mock `CacheManager`)**,平衡真实性和速度。 --- ## **最终修正代码(方法 1)** ```java @RunWith(SpringRunner.class) @SpringBootTest public class UserServiceImplCacheTest { @Autowired private UserService userService; @MockBean private UserRepository userRepository; @Test public void testGetUser_CacheHit() { UserDO testUser = new UserDO(); testUser.setId(1L); testUser.setEmail("test@example.com"); // 模拟第一次调用(数据库查询) when(userRepository.findById(1L)).thenReturn(Optional.of(testUser)); // 第一次调用(应访问数据库) UserGetRequestDTO request = new UserGetRequestDTO(); request.setUserId(1L); ResponseResult<UserGetResponseDTO> firstCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 第二次调用(相同参数,应走缓存) ResponseResult<UserGetResponseDTO> secondCall = userService.getUser(request); verify(userRepository, times(1)).findById(1L); // 确保没有再次查询数据库 } } ``` --- ## **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值