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

如何为私有变量编写JUnit测试用例?解决effectiveEndDate空指针异常

问题解决:NullPointerException 排查与私有变量的JUnit测试方案

一、effectiveEndDate 空指针异常的原因与解决

原因分析

测试环境中未正确加载Spring上下文或未注入@Value对应的配置属性,导致effectiveEndDate为null,调用DateTimeUtil.convertStringToDate(null)时触发空指针异常。

解决方案

1. 业务代码层面增加空判断(防御性编程)

在mapMarkupModelToEntity方法中先判空,避免空值传入转换工具类:

public CommodityMarkup mapMarkupModelToEntity(CommodityMarkupView commodityMarkupView) {
    CommodityMarkup commodityMarkup = new CommodityMarkup();
    if (effectiveEndDate != null) {
        commodityMarkup.setEffectiveEndDate(DateTimeUtil.convertStringToDate(effectiveEndDate));
    }
    // 其他属性映射逻辑
    return commodityMarkup;
}

2. 测试环境中正确注入属性

方式一:加载Spring上下文并指定测试属性

使用@SpringBootTest启动Spring上下文,通过@TestPropertySource直接指定测试用的属性值:

@SpringBootTest
@TestPropertySource(properties = {"default.effective.endDate=12/31/9999"})
public class CustomerCommodityMarkupMapServiceTest {
    @Autowired
    private CustomerCommodityMarkupMapService customerCommodityMarkupMapService;

    @Test
    void testMapMarkupModelToEntity() {
        CommodityMarkupView view = new CommodityMarkupView();
        // 模拟view的属性
        CommodityMarkup actualMarkup = customerCommodityMarkupMapService.mapMarkupModelToEntity(view);
        
        CommodityMarkup expectedMarkup = new CommodityMarkup();
        expectedMarkup.setEffectiveEndDate(DateTimeUtil.convertStringToDate("12/31/9999"));
        
        assertEquals(expectedMarkup, actualMarkup);
    }
}
方式二:单元测试中手动设置私有变量(不加载Spring上下文)

通过反射直接修改私有变量的值,适合轻量单元测试:

public class CustomerCommodityMarkupMapServiceTest {
    private CustomerCommodityMarkupMapService service = new CustomerCommodityMarkupMapService();

    @BeforeEach
    void setUp() throws NoSuchFieldException, IllegalAccessException {
        // 获取私有字段并设置可访问
        Field endDateField = CustomerCommodityMarkupMapService.class.getDeclaredField("effectiveEndDate");
        endDateField.setAccessible(true);
        // 设置测试用的属性值
        endDateField.set(service, "12/31/9999");
    }

    @Test
    void testMapMarkupModelToEntity() {
        CommodityMarkupView view = new CommodityMarkupView();
        CommodityMarkup actualMarkup = service.mapMarkupModelToEntity(view);
        
        CommodityMarkup expectedMarkup = new CommodityMarkup();
        expectedMarkup.setEffectiveEndDate(DateTimeUtil.convertStringToDate("12/31/9999"));
        
        assertEquals(expectedMarkup, actualMarkup);
    }
}

二、私有变量的JUnit测试方案

通常不建议直接测试私有变量,而是通过测试公共方法的行为来验证私有变量的作用。如果需要为不同私有变量值编写测试,推荐以下方案:

1. 重构为构造函数注入(推荐)

将私有变量改为构造函数注入,测试时可直接传入不同值,符合依赖注入原则,测试更简洁:

@Component
public class CustomerCommodityMarkupMapService {
    private final String effectiveEndDate;

    // 通过构造函数注入属性
    public CustomerCommodityMarkupMapService(@Value("${default.effective.endDate}") String effectiveEndDate) {
        this.effectiveEndDate = effectiveEndDate;
    }

    // 业务方法...
}

测试代码:

@Test
void testMapMarkupModelToEntityWithCustomEndDate() {
    String testEndDate = "01/01/2025";
    CustomerCommodityMarkupMapService service = new CustomerCommodityMarkupMapService(testEndDate);
    
    CommodityMarkup actualMarkup = service.mapMarkupModelToEntity(new CommodityMarkupView());
    assertEquals(DateTimeUtil.convertStringToDate(testEndDate), actualMarkup.getEffectiveEndDate());
}

2. 使用Spring工具类ReflectionTestUtils

如果是Spring组件,加载上下文后用ReflectionTestUtils快速设置私有变量:

@SpringBootTest
public class CustomerCommodityMarkupMapServiceTest {
    @Autowired
    private CustomerCommodityMarkupMapService service;

    @Test
    void testWithDifferentEndDate() {
        // 设置私有变量值
        ReflectionTestUtils.setField(service, "effectiveEndDate", "06/30/2024");
        
        CommodityMarkup actualMarkup = service.mapMarkupModelToEntity(new CommodityMarkupView());
        assertEquals(DateTimeUtil.convertStringToDate("06/30/2024"), actualMarkup.getEffectiveEndDate());
    }
}

3. 反射直接操作私有字段

如前文单元测试中的setUp方法所示,通过Java反射API直接修改私有变量,适合非Spring环境的单元测试。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:43:08