在使用 mockito 和 junit5 测试的同一个 class 中模拟 void 方法?
Mocking a void method in the same class that is under test with mockito and junit5?
我想在与 mockito 一起测试的同一个 class 中模拟一个 void 方法。
我可以用 @Spy 注释测试 class 来实现 not void 方法,然后使用下面的代码来 return 我想要的数据。
willAnswer(arg -> arg.getArgument(0))
.given(customerService)
.saveCustomer(any(Customer.class));
但是如何为 void 方法做到这一点。
(我已经尝试了 willDoNothing().given() 函数)
这是我的真实方法:
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()));
}
};
这是测试:
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());
}
这是模拟:
//other mocks...
@Mock
private RelationService relationService;
@Mock
private CustomerValidator customerValidator;
@InjectMocks
@Spy
private CustomerServiceImpl customerService;
每个依赖项都是用@Mock 模拟的。
什么都不适合我。只需要注意调用顺序
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
doNothing().when(yourMock).yourMethod(yourArgs);
这个 thread 处理类似的问题,使用间谍模拟静态工厂的特定方法应该可行。我见过有人做反向操作(在某些特定情况下使用 Mock 然后调用真正的方法),但从未亲自尝试过..
我想在与 mockito 一起测试的同一个 class 中模拟一个 void 方法。 我可以用 @Spy 注释测试 class 来实现 not void 方法,然后使用下面的代码来 return 我想要的数据。
willAnswer(arg -> arg.getArgument(0))
.given(customerService)
.saveCustomer(any(Customer.class));
但是如何为 void 方法做到这一点。 (我已经尝试了 willDoNothing().given() 函数)
这是我的真实方法:
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()));
}
};
这是测试:
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());
}
这是模拟:
//other mocks...
@Mock
private RelationService relationService;
@Mock
private CustomerValidator customerValidator;
@InjectMocks
@Spy
private CustomerServiceImpl customerService;
每个依赖项都是用@Mock 模拟的。
什么都不适合我。只需要注意调用顺序
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
doNothing().when(yourMock).yourMethod(yourArgs);
这个 thread 处理类似的问题,使用间谍模拟静态工厂的特定方法应该可行。我见过有人做反向操作(在某些特定情况下使用 Mock 然后调用真正的方法),但从未亲自尝试过..