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

Minecraft Fabric服务端模组单元测试搭建方案

Fabric服务端模组测试落地方案

基础规则:先解决测试代码混入生产包的问题

别用配置布尔开关的方案,直接用Gradle标准目录结构隔离代码:

  • 生产代码放src/main/java,只有这部分代码会被打进最终发布的mod jar
  • 不依赖游戏运行的单元测试代码放src/test/java,Gradle执行test任务时才会编译加载,完全不会进入生产包
  • 需要依赖Fabric/Minecraft类的集成测试代码放src/testmod/java,Fabric Loom插件会把这部分打成独立的测试附属mod,只有跑测试任务时才会加载,和生产代码完全隔离

对应三个测试要求的实现方式

1. 验证代码可正常编译

直接用Gradle原生的build任务即可,现有CI里的构建步骤已经覆盖这部分:只要./gradlew build执行过程中没有报错,就说明代码编译、依赖声明都没有问题,不需要额外加逻辑。

2. 验证代码可在Fabric服务端正常运行

优化现有CI里的服务端启动步骤,不用写额外代码:

  • 用Fabric Loom自带的runServer任务启动服务端,不要自己手动拼服务端包
  • CI脚本里监听服务端日志,当出现Done! For help, type "help"字样时,说明服务端、所有mod已经完全加载完成,没有启动崩溃
  • 检测到加载完成后等待10秒,向服务端进程输入stop指令正常关服,整个过程没有报错、崩溃就算通过
  • 如果启动过程中出现mod加载失败、类缺失、初始化异常,任务会直接退出,CI会判定为失败

3. 全功能逻辑覆盖(SQL读写、事件触发)

这部分分两层做,兼顾测试速度和覆盖度:

第一层:纯单元测试(不启动游戏,速度快)

先把核心逻辑和Fabric事件、Minecraft类解耦:

  • 不要把SQL读写逻辑直接写在玩家加入/离开的事件监听器匿名类里,单独抽一个PlayerDataSyncService类,把loadPlayerData、savePlayerData两个核心方法做成独立公开方法
  • 把需要同步的玩家字段(UUID、用户名、背包、经验、位置等)抽成普通Java POJO,核心同步逻辑只和这个POJO、数据源打交道,不直接依赖ServerPlayer这类Minecraft类
  • 事件监听器只做参数转换:玩家加入事件触发时,从ServerPlayer实例里提取字段,调用syncService的load方法拿到POJO,再把POJO里的值写回玩家对象;玩家离开时同理,从玩家对象提取字段生成POJO,调用save方法写库
  • 单元测试里直接用Junit5跑核心逻辑,数据库用H2的MySQL兼容模式做内存库,不需要搭真实MySQL服务,直接测SQL建表、读写、更新、异常处理的逻辑对不对,这部分在./gradlew test任务里自动执行。

第二层:集成测试(启动Fabric服务端,覆盖事件逻辑)

用Fabric官方提供的GameTest框架做,不需要自己搭模拟玩家连接的逻辑:

  • 测试代码全部放在之前说的src/testmod/java目录,注册一个测试专用的mod入口点,只有跑测试任务时才会加载
  • 监听ServerLifecycleEvents.SERVER_STARTED事件,在服务端完全启动后自动执行测试用例:
    • 先把模组的数据源切换到测试用的H2内存库,清空测试数据
    • 用GameTestHelper.createMockServerPlayer()方法创建服务端侧的模拟玩家对象,不需要真实客户端连接
    • 手动触发玩家加入流程:可以直接调用你自己写的加入事件处理逻辑,也可以通过Fabric事件总线抛出玩家加入对应事件,之后校验:模拟玩家的对应字段有没有被正确赋值、测试库里有没有生成对应玩家的初始记录
    • 修改模拟玩家的测试字段(比如修改经验值、给背包加测试物品),再触发玩家离开事件,之后校验测试库里的对应记录有没有同步更新
    • 所有断言通过就标记测试成功,任意步骤失败直接抛出异常,让服务端异常退出,CI就能捕获到失败
  • 这部分配置到runGametest任务里,CI执行./gradlew runGametest就能自动跑完所有用例,跑完会自动退出,不需要人工干预。

CI工作流最终执行顺序

现有GitHub Actions只要按顺序跑三个命令就能覆盖所有测试要求:

  1. ./gradlew test:执行所有单元测试,同时完成代码编译校验
  2. ./gradlew runServer:完成mod服务端加载校验
  3. ./gradlew runGametest:执行全链路集成测试,覆盖事件触发、SQL读写逻辑

不要用配置开关的方案:这种方式会把测试逻辑打进生产jar,不仅会增加jar体积,一旦开关逻辑写漏,还有可能在生产环境触发测试逻辑,污染线上数据库,用Gradle标准目录隔离是Java生态通用的成熟方案,没有这类风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:57:15