无法调用“”,因为“”为 null mockito /junit

Cannot invoke "" because "" is null mockito /junit

根据标题,我在测试服务时遇到了一个问题method.I假设它应该是一些配置问题或者更多是 mockito 的错误使用。

有 CustomerDataService 的代码

@Service
 public class CustomerDataService {

@Autowired
CustomerDataRepository customerDataRepository;

...

@Transactional
public void methodTotest(boolean consent, Long dialogId) {
    CustomerData customer = customerDataRepository.findCustomerByDialogId(dialogId);

    if (!consent) {
        
    customerDataRepository.deleteById(customer.getCustomerId());
    }else{
        customer.setConsentGiven(true);
        customerDataRepository.save(customer);
    }
}

在测试CustomerDataServiceTest @SpringBootTest class客户数据服务测试{

@Autowired
CustomerDataService customerDataService;

@MockBean
CustomerDataRepository customerDataRepository;

@Test
void removeCustomerDataWhenConsentIsNotGiven() {
    CustomerData customerDataTest = customerData;
    //when
    customerDataService.giveConsent(false,22L);
   

    //then
    
    
verify(customerDataRepository,times(1)).save(customerDataTest);
     }

错误是

java.lang.NullPointerException: Cannot invoke "com.mypackage.CustomerData.getCustomerId()" because "customer" is null

这是myMethod的第二行 提前致谢

假设您刚刚在将其发布到 Whosebug 之前更正了方法名称,并且您在测试中调用的方法:giveConsent 实际上与 CustomerDataService 的 methodTotest 是相同的方法。

在调用 customerDataService.giveConsent(false,22L); 之前,您需要将存储库配置为 return 一些测试(非空!或模拟)customerData 实体:

when(customerDataRepository.findCustomerByDialogId(22L)).thenReturn(customerDataTest);
customerDataService.giveConsent(false,22L);

注意:由于您将 false 作为第一个变量传递,因此您将进入此代码分支

    if (!consent) {  
      customerDataRepository.deleteById(customer.getCustomerId());
    }

并且在测试中您期望调用 save() 方法,因此测试将失败。

解决方法很简单。你模拟了一个 class customerDataRepository 但没有指示模拟如果调用相应的方法该做什么。 Mockito 模拟然后通过方法调用默认返回 doing nothing,如果有 return 值 return null。 由于您的 returned customerData 为空,因此您在调用此对象时会得到 NPE。在您的情况下,这是您通过调用 getCustomerId().

得到的错误情况

要解决此问题,只需指示您的模拟

@Test
void removeCustomerDataWhenConsentIsNotGiven() {
   CustomerData customerDataTest = customerData;
   //when
   Mockito.when(customerDataRepository.findCustomerByDialogId(Mockito.any())).thenReturn(new CustomerData()); // <-- Add this line
   customerDataService.giveConsent(false,22L);
   //then 
   verify(customerDataRepository,times(1)).save(customerDataTest);
}

您显然可以将 Mockito.any() 替换为 Mockito.anyInt()42 并将 new CustomerData() 替换为您之前创建的对象。我想你明白了 ;)