在使用 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 然后调用真正的方法),但从未亲自尝试过..