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

调用Mock方法时出现NullPointerException的原因与修复方案

问题:Mock依赖后仍抛出NullPointerException

在调用CustomerProfileService的getCustomerProfile方法时,标注位置抛出NullPointerException,但测试中已经Mock了CustomerProfileRepository,请问原因及修复方法?

类定义

@Service("customer-profile-service")
public class CustomerProfileService {
    CustomerProfileRepository customerProfileRepository;

    public CustomerProfileService(CustomerProfileRepository customerProfileRepository){
        this.customerProfileRepository = customerProfileRepository;
    }

    public CustomerProfile getCustomerProfile(RestConsumerRequest<MortgPointsFulfillRequest> consumerRequest) {

        RestConnectorResponse<RestConsumerResponse<CustomerProfile>> restConnectorResponseC1 = customerProfileRepository.customerProfileLookup(consumerRequest);        // <- NullPointerException
        ...
    }
}

测试用例

@ExtendWith(MockitoExtension.class)
public class CustomerProfileServiceTest {
    @Mock
    CustomerProfile customerProfile;

    @Mock
    RestConsumerRequest restConsumerRequest;

    @Mock
    CustomerProfileRepository customerProfileRepository;

    @Mock
    RestConnectorResponse<RestConsumerResponse<CustomerProfile>> restConnectorResponseC1;

    @Spy
    CustomerProfileService customerProfileService = new CustomerProfileService(customerProfileRepository);

    @Test
    public void getCustomerProfileTest() {
        doReturn(restConnectorResponseC1).when(customerProfileRepository).customerProfileLookup(restConsumerRequest);
        customerProfileService.getCustomerProfile(restConsumerRequest);
        Mockito.verify(customerProfileRepository, times(1)).customerProfileLookup(any());
    }
}

原因分析

  1. 泛型类型不匹配,Mock Stub未生效
    服务方法的参数是RestConsumerRequest<MortgPointsFulfillRequest>,但测试中Mock的restConsumerRequest是无泛型的原始类型。Mockito的参数匹配会严格校验类型(包括泛型),导致你定义的doReturn(...) stub不触发,customerProfileLookup返回默认的null,进而抛出NPE。

  2. Spy初始化时机错误,依赖未正确注入
    直接用@Spy注解手动创建CustomerProfileService实例时,Mockito可能还未完成customerProfileRepository Mock对象的初始化,导致注入的依赖是未初始化的无效对象(甚至是null)。


修复方案

1. 修正泛型类型匹配

将测试中的RestConsumerRequest Mock改为带正确泛型的版本:

@Mock
RestConsumerRequest<MortgPointsFulfillRequest> restConsumerRequest;

2. 正确初始化Service实例

推荐两种方式:

方式一:使用@InjectMocks自动注入依赖

替换手动创建Spy的方式,让Mockito自动将所有@Mock依赖注入到Service中:

@Mock
CustomerProfile customerProfile;

@Mock
RestConsumerRequest<MortgPointsFulfillRequest> restConsumerRequest;

@Mock
CustomerProfileRepository customerProfileRepository;

@Mock
RestConnectorResponse<RestConsumerResponse<CustomerProfile>> restConnectorResponseC1;

@InjectMocks
CustomerProfileService customerProfileService; // Mockito自动完成依赖注入

方式二:手动初始化Spy(保留Spy场景)

如果需要使用Spy,在@BeforeEach方法中初始化,确保Mock对象已创建完成:

@Mock
CustomerProfile customerProfile;

@Mock
RestConsumerRequest<MortgPointsFulfillRequest> restConsumerRequest;

@Mock
CustomerProfileRepository customerProfileRepository;

@Mock
RestConnectorResponse<RestConsumerResponse<CustomerProfile>> restConnectorResponseC1;

CustomerProfileService customerProfileService;

@BeforeEach
void setUp() {
    customerProfileService = Mockito.spy(new CustomerProfileService(customerProfileRepository));
}

3. 可选:优化参数匹配逻辑

如果不需要严格匹配特定的restConsumerRequest对象,可以用any()替代,避免参数匹配失败:

doReturn(restConnectorResponseC1).when(customerProfileRepository).customerProfileLookup(any());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:35:32