Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

as per title I am facing an issue when testing a service method.I suppose it should be some config problem or much more some wrong usage of mockito.

There is the code of the 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);
    }
}

In the test CustomerDataServiceTest

@SpringBootTest
class CustomerDataServiceTest {

@Autowired
CustomerDataService customerDataService;

@MockBean
CustomerDataRepository customerDataRepository;

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

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

The error is

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

this is the second line of the myMethod

like image 545
spring00 Avatar asked Jul 04 '26 02:07

spring00


2 Answers

The solution is simple. You mocked a class customerDataRepository but did not instruct it the mock what to do if the corresponding method is called. Mockito mocks then default back on doing nothing by method call and if there is a return value return null. Since your returned customerData is null you get your NPE when calling on this object. In your case this is in the error case that you get by calling getCustomerId().

To solve this issue simply instruct your mock

@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);
}

you can obviously replace Mockito.any() with Mockito.anyInt() or 42 and new CustomerData() with a object you previously created. I think you get the idea ;)

like image 59
GJohannes Avatar answered Jul 05 '26 16:07

GJohannes


Assuming that you have just corrected method names before posting it to Stackoverflow, and method you are calling in the test: giveConsent is, actually, the same method as methodTotest of the CustomerDataService.

Before calling customerDataService.giveConsent(false,22L);, you need to configure you repository to return some test (not null! or mocked) customerData entity:

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

Note: since you are passing false as 1st variable, you will get to this branch of code

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

And in the test you are expecting save() method to be called, so the test will fail.

like image 38
Idol Avatar answered Jul 05 '26 16:07

Idol



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!