Kotlin项目空指针异常:recordPartialWithdrawal非空错误修正指引
Kotlin单元测试空指针异常(recordPartialWithdrawal不能为null)修复方案
问题场景
运行下述Kotlin单元测试代码时触发空指针异常,报错提示:recordPartialWithdrawal不能为null
测试代码
@Test fun `should record partial Withdrawal`() { underTest.recordPartialWithdrawal(defaultUserId, Money.of(200.200, "EUR"), LocalDate.now()) val paymentRequestHistoryRequestCapture = argumentCaptor() verify(paymentRequestHistoryRepository).save<PaymentRequestHistory>(paymentRequestHistoryRequestCapture.capture()) assertThat(paymentRequestHistoryRequestCapture.firstValue).satisfies( Consumer { assertThat(it.type).isEqualTo(PaymentRequestType.OUTGOING_PARTIAL_WITHDRAWAL) assertThat(it.userId).isEqualTo(defaultUserId) assertThat(it.amount).isEqualTo(Money.of(200.200, "EUR")) } ) underTest.recordPartialWithdrawal(defaultUserId, Money.of(200.200, "EUR"), LocalDate.now()) }
核心原因
空指针异常直接原因是测试中的underTest实例未正确初始化,调用recordPartialWithdrawal方法时触发NPE。同时代码存在其他潜在问题:
argumentCaptor()未指定泛型类型,存在类型安全隐患- 重复调用
recordPartialWithdrawal但未做验证,属于冗余代码
修复步骤
- 初始化测试实例:确保
underTest对应的业务类在测试前完成实例化,依赖的paymentRequestHistoryRepository需通过Mock框架(如MockK/Mockito)初始化并注入。示例(MockK):private val paymentRequestHistoryRepository = mockk<PaymentRequestHistoryRepository>() private val underTest = YourServiceClass(paymentRequestHistoryRepository) // 替换为实际业务类名 - 指定ArgumentCaptor泛型:明确
argumentCaptor的目标类型,避免类型转换问题:val paymentRequestHistoryRequestCapture = argumentCaptor<PaymentRequestHistory>() - 清理冗余代码:删除未做验证的第二次
recordPartialWithdrawal调用,或补充对应的验证逻辑 - 校验参数非空:确认
defaultUserId、Money.of(200.200, "EUR")等入参不为null,必要时添加非空断言
修复后完整测试代码示例
import io.mockk.mockk import io.mockk.verify import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.assertj.core.api.Assertions.assertThat class YourServiceClassTest { // 替换为实际测试类名 private val paymentRequestHistoryRepository = mockk<PaymentRequestHistoryRepository>(relaxed = true) private lateinit var underTest: YourServiceClass private val defaultUserId = "test-user-id" @BeforeEach fun setUp() { underTest = YourServiceClass(paymentRequestHistoryRepository) } @Test fun `should record partial Withdrawal`() { val testAmount = Money.of(200.200, "EUR") val testDate = LocalDate.now() underTest.recordPartialWithdrawal(defaultUserId, testAmount, testDate) val capture = argumentCaptor<PaymentRequestHistory>() verify { paymentRequestHistoryRepository.save(capture.capture()) } val capturedHistory = capture.firstValue assertThat(capturedHistory.type).isEqualTo(PaymentRequestType.OUTGOING_PARTIAL_WITHDRAWAL) assertThat(capturedHistory.userId).isEqualTo(defaultUserId) assertThat(capturedHistory.amount).isEqualTo(testAmount) } }
内容的提问来源于stack exchange,提问作者nitin sharma
相关产品推荐
相关产品推荐

