i want to mock a void method in the same class that is under test with mockito. i can do that for not void method with annotating test class with @Spy and then use below code to return data i want.
willAnswer(arg -> arg.getArgument(0))
.given(customerService)
.saveCustomer(any(Customer.class));
but how can do that for void method. (i already try willDoNothing().given() function)
this is my real method:
public void deleteCustomersByTenantId(TenantId tenantId) throws ThingsboardException {
log.trace("Executing deleteCustomersByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, "Incorrect tenantId " tenantId);
customersByTenantRemover.removeEntities(tenantId, tenantId);
}
public void deleteCustomer(TenantId tenantId, CustomerId customerId) throws ThingsboardException {
log.trace("Executing deleteCustomer [{}]", customerId);
Validator.validateId(customerId, INCORRECT_CUSTOMER_ID customerId);
Customer customer = findCustomerById(tenantId, customerId);
if (customer == null) {
throw new IncorrectParameterException("Unable to delete non-existent customer.");
}
entityViewService.unassignCustomerEntityViews(customer.getTenantId(), customerId);
assetService.unassignCustomerAssets(customer.getTenantId(), customerId);
userService.deleteCustomerUsers(customer.getTenantId(), customerId);
deleteEntityRelations(tenantId, customerId);
entityGroupDao.deleteEntityGroupsByTenantIdAndCustomerId(customer.getTenantId(), customerId);
customerDao.removeById(tenantId, customerId.getId());
}
private final PaginatedRemover<TenantId, Customer> customersByTenantRemover =
new PaginatedRemover<>() {
@Override
protected PageData<Customer> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return customerDao.findCustomersByTenantId(id.getId(), pageLink);
}
@Override
protected void removeEntity(TenantId tenantId, Customer entity) throws ThingsboardException {
deleteCustomer(tenantId, new CustomerId(entity.getUuidId()));
}
};
and this is the test:
void deleteCustomersByTenantId() throws ThingsboardException {
//given
Customer customer = new Customer();
customer.setId(CUSTOMER_ID);
customer.setTenantId(TENANT_ID);
ArgumentCaptor<CustomerId> customerIdArgumentCaptor = ArgumentCaptor.forClass(CustomerId.class);
var pageData = new PageData<>(Collections.singletonList(customer), 1 ,1 , false);
given(customerDao.findCustomersByTenantId(any(UUID.class), any(PageLink.class)))
.willReturn(pageData);
doNothing()
.when(customerService)
.deleteCustomer(any(), any());
//when
customerService.deleteCustomersByTenantId(TENANT_ID);
//then
then(customerDao)
.should(times(1))
.findCustomersByTenantId(any(UUID.class), any(PageLink.class));
then(customerService)
.should(times(1))
.deleteCustomer(any(TenantId.class), customerIdArgumentCaptor.capture());
assertEquals(CUSTOMER_ID, customerIdArgumentCaptor.getValue());
}
this is the Mocks:
//other mocks...
@Mock
private RelationService relationService;
@Mock
private CustomerValidator customerValidator;
@InjectMocks
@Spy
private CustomerServiceImpl customerService;
every dependency is mock with @Mock.
CodePudding user response:
Do nothing works for me. Just pay attention to the calling order
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
doNothing().when(yourMock).yourMethod(yourArgs);
This thread treats a similar problem, using a spy to mock specific methods with static factories should work. I've seen people doing to reverse operation (Use a Mock and then call the real method in some specific cases), but never tried it personally..