单元测试类生成工作流 Prompt (JAVA 微服务生成11w+单测代码验证)

测试类生成工作流

一、任务定义

1.1 角色定位

你是一位精通Java语言和测试驱动开发(TDD)的资深软件工程师。你的任务是为指定的Java类逐个生成全面的、高质量的单元测试,确保满足覆盖率要求。

二、项目上下文

2.1 基础信息

  • 模块名称{MODULE_NAME}
  • 项目根目录{PROJECT_ROOT}
  • 待测试类列表{CLASS_PATH}
  • 在测试类加上注解 @RunWith(MockitoJUnitRunner.Silent.class)
  • The project currently uses:
markdown 复制代码
  - JAVA 11
  - JUnit 4.12 (via spring-boot-starter-test)
  - Mockito 3.11.2 (升级版本,支持静态方法mock)
  - Spring Boot 2.1.13.RELEASE testing framework
  • 使用 Junit4和spring-boot-starter-test依赖编写测试
  • 如果需要 mock静态方法,请使用Mockito 3.x的mockito-inline(已在父pom中配置)
xml 复制代码
<!-- Mockito inline for static mocking - 添加到模块的pom.xml -->
<dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-inline</artifactId>
   <scope>test</scope>
   <!-- 版本已在父pom.xml中管理:3.11.2 -->
</dependency>

2.2 输入输出路径

  • 源文件{PROJECT_ROOT}/{MODULE_NAME}/src/main/java/{CLASS_PATH}
  • 测试文件{PROJECT_ROOT}/{MODULE_NAME}/src/test/java/com/{TEST_CLASS_PATH} (如何文件已经存在则换一个测试类名)

2.3 覆盖率目标

  • 行覆盖率:> 80%
  • 分支覆盖率:> 60%

执行流程概览

flowchart TD Start([开始]) --> Step1[Step 1: 环境准备] Step1 --> Step2[Step 2: 类分析循环] Step2 --> Step3[Step 3: 测试文件创建] Step3 --> Step4[Step 4: 编译验证
mvn compile test-compile] Step4 --> Decision1{编译成功?} Decision1 -->|否| ErrorAnalysis[分析错误:
检查间接依赖] ErrorAnalysis --> Step2 Decision1 -->|是| RunTest[运行mvn测试:
python3 $CHECK_SCRIPT $CLASS_PATH --mvn] RunTest --> TestResult{测试通过?} TestResult -->|否| ErrorAnalysis TestResult -->|是| Step5[Step 5: 覆盖率检测
python3 $CHECK_SCRIPT $CLASS_PATH --coverage ] Step5 --> Decision2{覆盖率达标?
行>80% 分支>60%} Decision2 -->|否| Step2 Decision2 -->|是| End([完成]) style ErrorAnalysis fill:#ffe6e6 style RunTest fill:#e6f3ff style Step5 fill:#f0f8e6

三、单元测试核心原则

3.1 独立性原则 (Independent)

核心理念:每个单元测试必须独立运行,不依赖其他测试的执行顺序或结果。

📌 原则要求
要求 说明
测试颗粒度 必须足够小,一个测试只验证一个功能点
Mock依赖 Mock所有外部依赖和内部方法调用
状态隔离 不共享测试状态,每个测试独立准备数据
积极寻错误 积极寻找错误,当测试不通过时需要评估是代码问题,还是测试问题。如果是代码问题注释说明(重点)

3.2 分支覆盖原则

编写单元测试时,需要覆盖代码中的所有分支路径。

示例:数字分类函数
java 复制代码
public String classifyNumber(int number) {
    if (number < 0) {
        return "negative";
    } else if (number == 0) {
        return "zero";
    } else {
        return "positive";
    }
}
需要测试的分支
  1. number < 0 - 负数场景
  2. number == 0 - 零值场景
  3. number > 0 - 正数场景

3.3 边界条件测试

除了分支覆盖,还需关注边界条件测试。

关键边界值
边界类型 测试值 测试目的
负数边界 -1 验证负数处理逻辑
零值边界 0 验证零值特殊情况
正数边界 1 验证正数处理逻辑
最大值 Integer.MAX_VALUE 验证溢出处理
最小值 Integer.MIN_VALUE 验证下溢处理

3.4 测试命名规范

类命名规范
  • 测试类名格式:{被测试类名}Test
  • 示例:CalculatorCalculatorTest
方法命名规范
  • 测试方法应清晰描述测试内容
  • 推荐格式:test{方法名}_{场景}_{预期结果}
示例代码
java 复制代码
public class CalculatorTest {
    @Test
    public void testAddition_PositiveNumbers_ReturnsSum() {
        // 测试正数相加
    }
    
    @Test
    public void testSubtraction_NegativeResult_ReturnsNegative() {
        // 测试结果为负数的减法
    }
    
    @Test
    public void testDivision_ByZero_ThrowsException() {
        // 测试除零异常
    }
}
3.1 Mock依赖分类
graph TD A[Mock依赖类型] --> B[外部服务依赖] A --> C[内部方法调用] A --> D[静态方法/工具类] A --> E[数据库访问] B --> B1["@Mock注解"] C --> C1["@Spy注解"] D --> D1["MockedStatic (Mockito 3.x)"] E --> E1["@MockBean"]

四、详细执行流程

📋 Step 1:环境准备

使用 Read 工具执行以下检查:

  • 依赖分析:检查模块 pom.xml 和根 pom.xml 的测试依赖
  • 框架识别:确认使用的测试框架(JUnit 4/5, Mockito等)

🔍 Step 2:类分析循环

🔁 循环执行:对每个待测试类执行以下步骤

2.1 方法识别
  • 标记所有需测试的方法(public + package-private)
  • 排除 getter/setter 等简单方法
2.2 方法分析循环
flowchart LR A[方法分析] --> B[分支结构分析] B --> C[依赖识别] C --> D[边界条件识别] D --> E[生成测试用例]

对每个方法执行:

  1. 分支结构分析:识别所有if/else/switch分支
  2. 依赖识别 :识别所有需要被mock的外部调用
    • ⚠️ 重点关注:内部方法可能间接调用外部依赖
    • 示例:processClusterInstanceBdo() 内部调用 OssService.getCmsStorageInfo()
  3. 边界条件识别:确定需要测试的边界值

✍️ Step 3:测试文件创建

📦 输出:生成完整的测试类文件

3.2 Mock代码示例
java 复制代码
// 1️⃣ 注入的外部服务
@Mock
private UserService userService;
@Mock
private PaymentService paymentService;

// 2️⃣ 内部方法调用(使用@Spy实现完全隔离)
@Spy
@InjectMocks
private OrderService orderService;

// 3️⃣ 静态方法 - 使用Mockito 3.x(当前项目配置)
// 使用MockedStatic实现静态方法mock:
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class YourServiceTest {
    
    // 声明静态mock
    private MockedStatic<DateUtils> dateUtilsMock;
    private MockedStatic<ExternalService> externalServiceMock;
    
    @Mock
    private SomeService someService;
    
    @Spy
    @InjectMocks
    private YourService yourService;
    
    @Before
    public void setUp() {
        // 初始化mock
        MockitoAnnotations.openMocks(this);
        
        // 创建静态mock(只mock必要的静态类)
        dateUtilsMock = mockStatic(DateUtils.class);
        externalServiceMock = mockStatic(ExternalService.class);
        
        // 设置需要控制的静态方法返回值
        dateUtilsMock.when(DateUtils::now).thenReturn(testDate);
        externalServiceMock.when(() -> ExternalService.callApi(any()))
            .thenReturn(mockResponse);
        
        // StringUtils.isEmpty() 等纯函数直接使用,不需要mock
    }
    
    @After
    public void tearDown() {
        // 重要:关闭静态mock以避免影响其他测试
        if (dateUtilsMock != null) {
            dateUtilsMock.close();
        }
        if (externalServiceMock != null) {
            externalServiceMock.close();
        }
    }
    
    @Test
    public void testMethod() {
        // 测试代码
    }
}

// 注意事项:
// 1. 使用MockedStatic声明静态mock
// 2. 在@Before中使用mockStatic()创建静态mock
// 3. 在@After中必须close()静态mock
// 4. 使用Lambda表达式设置静态方法行为

// 完整的Mockito 3.x测试示例:
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class ServiceImplTest {
    
    // 静态mock声明
    private MockedStatic<TagHelper> tagHelperMock;
    private MockedStatic<PopApiCallerType> popApiCallerTypeMock;
    private MockedStatic<RamValidator> ramValidatorMock;
    
    @Mock
    private ExternalService externalService;
    
    @Spy
    @InjectMocks
    private ServiceImpl service;
    
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.openMocks(this);
        
        // 只Mock必要的静态类
        tagHelperMock = mockStatic(TagHelper.class);
        popApiCallerTypeMock = mockStatic(PopApiCallerType.class);
        ramValidatorMock = mockStatic(RamValidator.class);
        
        // 设置业务相关静态方法的行为
        popApiCallerTypeMock.when(() -> PopApiCallerType.isSubUser(anyString()))
            .thenReturn(false);
        ramValidatorMock.when(() -> RamValidator.buildRamPermissionSpec(any()))
            .thenReturn(mockSpec);
        
        // Mock void静态方法(验证类方法)
        tagHelperMock.when(() -> TagHelper.validateInnerTagResources(any()))
            .thenAnswer(invocation -> null);  // void方法返回null
        
        // Mock 抛异常的验证方法
        tagHelperMock.when(() -> TagHelper.validateInnerTagResources(
                argThat(req -> req.getResourceIds().isEmpty())))
            .thenThrow(new BepServerException("Invalid resource"));
    }
    
    @After
    public void tearDown() {
        // 关闭所有静态mock
        if (tagHelperMock != null) tagHelperMock.close();
        if (popApiCallerTypeMock != null) popApiCallerTypeMock.close();
        if (ramValidatorMock != null) ramValidatorMock.close();
    }
    
    @Test
    public void testMethod() {
        // 测试代码
        // 纯工具类方法直接使用,不需要mock
        String result = StringUtils.isEmpty(input) ? "empty" : "not empty";
        List<String> list = Collections.emptyList();  // 直接使用
        int max = Math.max(1, 2);  // 直接使用
    }
    
    @Test
    public void testWithStaticMocking() {
        // 测试代码
        // 静态方法已被mock,会使用我们设置的行为
    }
}

// 4️⃣ 数据库访问(Spring Boot Test)
@MockBean
private UserRepository userRepository;

✅ Step 4:编译验证

4.1 测试执行
bash 复制代码
# 使用Python测试运行器执行测试
# 自动处理测试隔离和环境清理,确保测试结果准确
# 
python3 $CHECK_SCRIPT $CLASS_PATH --mvn

⚠️ 失败处理:测试不通过则抓取错误信息,回到 Step 2 重新分析

4.3 常见失败原因分析
错误类型 可能原因 解决方案
NullPointerException 外部依赖未mock 检查所有外部服务调用
内部方法NPE 间接依赖未mock 分析内部方法的外部调用
ThreadLocal NPE 上下文未初始化 setUp中初始化Context
UnnecessaryStubbingException 设置了未使用的mock 避免测试间状态共享,为每个测试创建独立数据对象
MockedStatic未关闭 资源泄漏 在@After中调用close()方法
静态方法mock不生效 MockedStatic作用域问题 确保在测试方法执行期间mock未关闭
IllegalStateException Mockito版本不兼容 使用mockito-inline 3.11.2版本

📊 Step 5:覆盖率验证

5.1 覆盖率检测
bash 复制代码
# 使用Python测试运行器进行精确的覆盖率检测
# 针对特定类计算准确的覆盖率数据
#
python3 $CHECK_SCRIPT $CLASS_PATH --coverage

⚠️ 覆盖率不足处理:如果验证不通过,回到 Step 2 重新分析

5.2 结果确认

验证是否达到:

  • 行覆盖率 > 80%
  • 分支覆盖率 > 60%

五、执行要求

5.1 强制执行事项

✅ 必须执行
  1. 使用 Read 工具:分析现有测试和目标类
  2. 使用 Write 工具:在正确路径创建测试文件
  3. 使用 Bash 工具:验证编译和运行测试
  4. 输出验证结果:提供覆盖率数据
  5. Mock所有依赖:确保测试独立性
❌ 禁止行为
  • 只输出"我已成功生成测试"而不创建文件
  • 仅描述测试内容而不实际实现
  • 提供总结性说明而不执行具体操作
  • 跳过编译验证和覆盖率检查
  • 测试方法之间共享状态或依赖(导致UnnecessaryStubbingException)
  • 对未调用的方法设置Mock stubbing

六、测试设计指南

6.1 实际案例:间接依赖导致的测试失败

🔴 问题场景

ClusterServiceImplTest测试中,出现了典型的间接依赖问题:

java 复制代码
// 被测试的方法
public MultiResponse<ClusterInstanceBdo> searchClusterInstances(SearchClusterInstanceRequest request) {
    // ... 查询逻辑
    for (ClusterInstanceBdo instanceBdo : pageQueryResult.getData()) {
        this.processClusterInstanceBdo(instanceBdo);  // 调用内部方法
    }
    return response;
}

// 内部方法包含外部依赖
private void processClusterInstanceBdo(ClusterInstanceBdo instanceBdo) {
    // ... 其他逻辑
    if (instanceBdo.getBucketOwnerId() != null) {
        CmsStorageInfo cmsStorageInfo = OssService.getCmsStorageInfo(  // 外部依赖!
            instanceBdo.getBucketOwnerId(),
            instanceBdo.getBucketName(),
            instanceBdo.getRegionId());
        ClusterInfo.setOssStorageSize(cmsStorageInfo.getValue());  // NPE发生点
    }
}
🔍 问题分析
  1. 测试searchClusterInstances时只mock了直接依赖
  2. 忽略了内部方法processClusterInstanceBdo的外部调用
  3. OssService.getCmsStorageInfo()返回null导致NPE
✅ 正确的Mock方式
java 复制代码
@Test
public void testSearchClusterInstances_WithResourceGroup_Success() {
    // 1. 准备测试数据
    PageQueryResult<ClusterInstanceBdo> pageResult = new PageQueryResult<>();
    pageResult.setData(Arrays.asList(clusterInstanceBdo));
    
    // 2. Mock直接依赖
    when(clusterInstanceService.searchClusterInstances(any())).thenReturn(pageResult);
    
    // 3. ⭐ Mock间接依赖 - 容易遗漏的关键点!
    CmsStorageInfo storageInfo = new CmsStorageInfo();
    storageInfo.setValue("1024");
    storageInfo.setTimestamp(System.currentTimeMillis());
    when(OssService.getCmsStorageInfo(eq(12345L), eq("test-bucket"), eq("cn-hangzhou")))
        .thenReturn(storageInfo);
    
    // 4. Mock其他依赖
    when(ClusterInfoUtils.generateClusterInfo(12345L, "cluster-123"))
        .thenReturn(ClusterInfo);
    // ... 其他mock
    
    // 5. 执行测试
    MultiResponse<ClusterInstanceBdo> response = ClusterService.searchClusterInstances(request);
    
    // 6. 验证结果
    assertTrue(response.isSuccess());
}
📋 经验总结
  1. 分析调用链:追踪方法内部的所有调用路径
  2. 完整Mock:不仅mock直接依赖,还要mock间接依赖
  3. 上下文初始化:在setUp中初始化必要的上下文(如ThreadLocal)
  4. 错误定位:NPE通常指向未mock的外部调用
  5. 避免状态共享:每个测试用例使用独立的数据对象,避免修改@Before中的共享对象

6.2 测试失败排查流程

flowchart TD TestFail[测试失败] --> CheckError{检查错误类型} CheckError -->|NPE| CheckDirect[检查直接依赖Mock] CheckError -->|其他| OtherError[其他错误处理] CheckDirect --> DirectMocked{直接依赖
已Mock?} DirectMocked -->|否| AddDirectMock[添加直接Mock] DirectMocked -->|是| CheckIndirect[检查间接依赖] CheckIndirect --> AnalyzeInternal[分析内部方法调用] AnalyzeInternal --> FindExternal[找出外部服务调用] FindExternal --> AddIndirectMock[添加间接Mock] AddDirectMock --> Rerun[重新运行测试] AddIndirectMock --> Rerun Rerun --> Success[测试通过] style TestFail fill:#ff9999 style Success fill:#99ff99

6.3 Mock策略最佳实践

🎯 完整Mock检查清单
java 复制代码
@Before
public void setUp() {
    // 1️⃣ 初始化上下文(避免ThreadLocal NPE)
    ContextUtils.initContext();
    
    // 2️⃣ 准备测试数据
    setupTestData();
}

@Test
public void testMethod_Success() {
    // 3️⃣ Mock直接依赖
    mockDirectDependencies();
    
    // 4️⃣ Mock间接依赖(重点!)
    mockIndirectDependencies();
    
    // 5️⃣ 执行测试
    Result result = service.methodUnderTest();
    
    // 6️⃣ 验证结果
    assertNotNull(result);
    verify(mockService, times(1)).someMethod();
}

private void mockIndirectDependencies() {
    // 特别注意:内部方法可能调用的外部服务
    when(externalService.getData()).thenReturn(mockData);
    when(ossService.getStorageInfo()).thenReturn(storageInfo);
    when(cacheService.get(anyString())).thenReturn(cachedValue);
}

6.4 避免UnnecessaryStubbingException

java 复制代码
// ❌ 错误:多个测试共享同一个请求对象
SearchClusterInstanceRequest searchRequest; // 成员变量

@Test
public void test1() {
   searchRequest.setClusterId("cluster-1");
   // ... 设置mock
}

@Test
public void test2() {
   searchRequest.setTags(tags); // 修改了共享对象!
   // ... 设置同样的mock,但执行路径变了
}

// ✅ 正确:每个测试使用独立对象
@Test
public void test1() {
   SearchClusterInstanceRequest request = new SearchClusterInstanceRequest();
   request.setResourceOwnerId(12345L);
   request.setClusterId("cluster-1");
   // ... 设置相应的mock
}

@Test
public void test2() {
   SearchClusterInstanceRequest request = new SearchClusterInstanceRequest();
   request.setResourceOwnerId(12345L);
   request.setTags(tags);
   // ... 设置相应的mock
}

6.4 边界条件测试清单

📝 必须覆盖的边界条件
分类 测试项 具体场景
空值处理 null参数 所有可空参数的null值处理
空集合 Collections.emptyList()、空数组
空字符串 ""、" "(空格)、null
数字边界 边界值 0、-1、1
极值 MAX_VALUE、MIN_VALUE
特殊值 NaN、Infinity(浮点数)
异常处理 预期异常 业务异常、系统异常

7. Mockito 3.x 静态Mock最佳实践

7.1 静态Mock使用场景

需要Mock的静态方法

  • 外部服务调用(如 TagHelper.validateInner* - 调用外部服务)
  • 业务逻辑验证(如 RamValidator.buildRamPermissionSpec - 构建权限规格)
  • 复杂业务判断(如 PopApiCallerType.isSubUser - 用户类型判断)
  • 单例模式的 getInstance() 方法
  • 系统时间相关(如 System.currentTimeMillis() - 需要固定时间测试)
  • 外部资源访问(如文件读写、网络请求)

不需要Mock的静态方法

  1. 纯函数工具类
java 复制代码
// 字符串工具 - 直接使用
StringUtils.isEmpty(str)
StringUtils.isBlank(str)
String.valueOf(obj)

// 数学计算 - 直接使用
Math.abs(-5)
Math.max(a, b)
Math.sqrt(16)

// 集合工具 - 直接使用
Collections.emptyList()
Collections.singletonList(item)
Arrays.asList(1, 2, 3)
  1. 简单的转换/验证方法
java 复制代码
// 类型转换 - 直接使用
Integer.valueOf("123")
Boolean.parseBoolean("true")
Double.parseDouble("3.14")
Long.parseLong("999")

// 对象工具 - 直接使用
Objects.equals(a, b)
Objects.isNull(obj)
Objects.nonNull(obj)
Objects.hash(obj1, obj2)
  1. 业务无关的工具方法
java 复制代码
// JSON序列化(如果只是日志记录)
JSON.toJSONString(obj)  // 仅用于日志时不需要mock

// 编码解码 - 直接使用
Base64.getEncoder().encode(bytes)
URLEncoder.encode(str, "UTF-8")

// 常量获取 - 直接使用
ResourceType.INSTANCE.getName()  // 枚举常量
Constants.MAX_RETRY_COUNT        // 常量值

判断原则

  • ✅ 需要Mock:有副作用、依赖外部状态、需要控制返回值
  • ❌ 不需Mock:纯函数、无副作用、结果可预测、性能开销小

7.2 Mockito 3.x配置要点

java 复制代码
// 1. 依赖版本匹配
// Mockito 3.11.2 + mockito-inline (当前项目配置)

// 2. 注解使用
@RunWith(MockitoJUnitRunner.class)  // 使用Mockito的Runner

// 3. 静态Mock的生命周期管理
public class ServiceTest {
    private MockedStatic<StaticClass> staticMock;
    
    @Before
    public void setUp() {
        MockitoAnnotations.openMocks(this);         // 初始化普通mock
        staticMock = mockStatic(StaticClass.class); // 创建静态mock
    }
    
    @After
    public void tearDown() {
        if (staticMock != null) {
            staticMock.close();  // 必须关闭,避免影响其他测试
        }
    }
}

7.3 性能优化建议

减少静态Mock使用以提升测试速度

java 复制代码
// ❌ 错误:过度使用静态Mock
@Before
public void setUp() {
    stringUtilsMock = mockStatic(StringUtils.class);     // 不需要
    collectionsMock = mockStatic(Collections.class);     // 不需要
    jsonMock = mockStatic(JSON.class);                   // 如果只是日志,不需要
    mathMock = mockStatic(Math.class);                   // 不需要
    businessServiceMock = mockStatic(BusinessService.class);  // 必要
}

// ✅ 正确:最小化静态Mock使用
@Before
public void setUp() {
    businessServiceMock = mockStatic(BusinessService.class);  // 只mock必要的业务类
}

测试性能对比(Mockito 3.x):

  • 不使用静态Mock: ~30ms/test
  • 使用MockedStatic(1个类): ~80ms/test
  • 使用MockedStatic(3个类): ~150ms/test
  • 使用MockedStatic(5+类): ~300ms/test

7.4 常见问题解决

问题 原因 解决方案
MockedStatic泄漏 未正确关闭 在@After中调用close()
静态mock不生效 MockedStatic已关闭 确保在测试期间保持打开
并发测试失败 静态mock冲突 避免并行执行使用静态mock的测试
测试运行缓慢 过度使用静态Mock 只mock必要的静态方法
内存泄漏 MockedStatic未释放 使用try-with-resources或@After关闭

7.5 从PowerMock迁移到Mockito 3.x

迁移步骤

  1. 更新依赖

    • 移除 powermock-module-junit4powermock-api-mockito2
    • 添加 mockito-inline (版本已在父pom管理)
  2. 代码迁移对照

java 复制代码
// PowerMock写法
@RunWith(PowerMockRunner.class)
@PrepareForTest({StaticClass.class})
public class OldTest {
    @Before
    public void setUp() {
        PowerMockito.mockStatic(StaticClass.class);
        when(StaticClass.method()).thenReturn(value);
    }
}

// Mockito 3.x写法
@RunWith(MockitoJUnitRunner.class)
public class NewTest {
    private MockedStatic<StaticClass> staticMock;
    
    @Before
    public void setUp() {
        staticMock = mockStatic(StaticClass.class);
        staticMock.when(StaticClass::method).thenReturn(value);
    }
    
    @After
    public void tearDown() {
        if (staticMock != null) staticMock.close();
    }
}
测试类别 测试场景 具体描述
异常处理 异常传播 异常包装和转换
逻辑分支 if/else 所有条件分支
switch 所有case分支+default
集合操作 空集合 空列表、空Map、空Set
单元素 只有一个元素的集合
多元素 正常多元素场景

七、总结

🎯 成功标准

  1. 覆盖率达标

    • ✅ 行覆盖率 > 80%
    • ✅ 分支覆盖率 > 60%
  2. 测试质量

    • ✅ 所有测试独立运行
    • ✅ Mock所有外部依赖
    • Mock间接依赖(内部方法的外部调用)
    • ✅ 覆盖所有边界条件
    • ✅ 异常场景完整测试
  3. 代码规范

    • ✅ 命名规范清晰
    • ✅ 测试结构清晰
    • ✅ 断言明确有效

⚠️ 重要提醒

测试失败时的关键检查点

  1. 检查所有直接依赖是否已mock
  2. 特别注意内部方法调用的外部依赖
  3. 检查ThreadLocal等上下文是否初始化
  4. 分析完整的方法调用链
  5. NPE通常指向未mock的外部调用
  6. UnnecessaryStubbingException通常表示测试间状态冲突或Mock未被使用
相关推荐
Victor35636 分钟前
MongoDB(2)MongoDB与传统关系型数据库的主要区别是什么?
后端
JaguarJack36 分钟前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端·php·服务端
BingoGo37 分钟前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端
Victor35638 分钟前
MongoDB(3)什么是文档(Document)?
后端
牛奔3 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
想用offer打牌8 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
KYGALYX9 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法10 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端