如何使用mockito的验证方法验证我的sendMessage方法是通过Msg.SAVE还是通过Msg.UPDATE调用的。
@Service
public class CustomerService {
private final CustomerRepository customerRepository;
private final SendMessageInTopic messageInTopic;
public CustomerService (CustomerRepository customerRepository, SendMessageInTopic messageInTopic)
{
this.customerRepository = customerRepository;
this.messageInTopic= messageInTopic;
}
public Customer saveCustomer(Customer savedCustomer) {
Customer customer = customerRepository
.findCustomerByEmail(savedCustomer.getEmail());
if(customer != null) {
customer.setFirstName(savedCustomer.getFirstName());
customer.setLastName(savedCustomer.getLastName());
customer.setPhoneNumber(savedCustomer.getPhoneNumber());
messageInTopic.sendMessage(savedCustomer.getId(),Msg.SAVE)
} else {
customer = new Customer();
customer.setFirstName(savedCustomer.getFirstName());
customer.setLastName(savedCustomer.getLastName());
customer.setEmail(savedCustomer.getEmail());
customer.setPhoneNumber(savedCustomer.getPhoneNumber());
messageInTopic.sendMessage(savedCustomer.getId(),Msg.Update)
}
return customerRepository.save(customer);
}
}
public class CustomerServiceTest{
private final CustomerRepository customerRepository = mock(CustomerRepository.class);
private final CustomerService customerService = mock(CustomerService.class);
private final SendMessageInTopic messageInTopic = mock(SendMessageInTopic.class);
private final CustomerMapper customerMapper = mock(CustomerMapper.class);
@Test
void whenSaveCustomerThenMsgSAVEOrUPDATE() {
// Given
final var customerId = "123456";
final var customer =
new CustomerDto(ensUserId, 'james', 'GREWAN', '32766666', '[email protected]');
final customerEntity = mock(Customer.class);
when(customerRepository.findCustomerByEmail(customer.getEmail())
.thenReturn(Optional.of(customerEntity));
when(customerRepository.save(customerEntity)).thenReturn(customerEntity);
when(customerMapper.toDto(customerEntity)).thenReturn(customer);
// When
final var result = customrService.saveCustomer(customer);
// Then
assertEquals(result, customer);
verify(messageInTopic, times(1)).sendMessage(result.getId(),Msg.SAVE);
}
}
verify(messageInTopic, times(1)).sendMessage(result.getId(),Msg.SAVE);:这是我将测试是否在创建案例中使用 Msg.SAVE 参数调用我的 sendMessage 方法或更新情况下的 Msg.UPDATE 参数。
请问如何进行此测试?
@knittl 是正确的。您的验证呼叫是否正确。问题是您正在嘲笑您要测试的课程。当您调用
mock(CustomerService.class)
时,Mockito 实际上是在创建一个存根所有方法的类(即覆盖它们并返回默认值):
class CustomerServiceMock extends CustomerService {
...
@Override
public Customer saveCustomer(Customer savedCustomer) {
// Stub
return null;
}
...
}
因此
customerService.saveCustomer(customer)
将返回 null,因为 customerService 实际上是一个 CustomerServiceMock。 assertEquals(result, customer)
会因此而失败。解决方案是将 customerService = mock(CustomerService.class);
替换为 customerService = new CustomerService(customerRepository, messageInTopic)
。请注意,customerRepository 和 messageInTopic 是您声明的模拟。
然而,由于这些行,你的assertEqual应该仍然会失败。
when(customerRepository.findCustomerByEmail(customer.getEmail())
.thenReturn(Optional.of(customerEntity));
when(customerRepository.save(customerEntity)).thenReturn(customerEntity);
这些使得
saveCustomer(customer)
返回模拟 customerEntity
。
assertEquals
失败,因为 customerEntity
与 customer
不匹配。verify(messageInTopic ...
也不起作用,因为sendMessage(result.getId(),Msg.SAVE)
相当于sendMessage(null, Msg.SAVE)
。这是因为 customerEntity
是一个 mock(Customer.class)
,这意味着 customerEntity.getId
看起来像这样:class CustomerMock extends Customer {
...
public String getId() {
// Stub
return null;
}
...
}
有很多方法可以解决这个问题。我的建议是删除
customerEntity
并使用 customer
,如下所示:
when(customerRepository.findCustomerByEmail(customer.getEmail())
.thenReturn(Optional.of(customer));
when(customerRepository.save(customer)).thenReturn(customer);
这将使 saveCustomer 返回
customer
,以便assertEqual 通过。它还将使 savedCustomer.getId()
和 result.getId()
相等。 findCustomerByEmail
无论如何都应该返回真正的客户,所以这对我来说最有意义。
也仅供参考:Matchers.eq 和直接使用参数在功能上是相同的,所以它不会改变任何东西:
verify(messageInTopic, times(1)).sendMessage(result.getId(),Msg.SAVE);
verify(messageInTopic, times(1)).sendMessage(Matchers.eq(result.getId()), Matchers.eq(Msg.SAVE));
那么为什么要使用 Matchers.eq 呢?假设您只想验证是否使用 Msg.SAVE 与 Msg.UPDATE 调用了 sendMessage,并且不关心 id。问题是你不能混合匹配器和直接参数,所以这不起作用:
verify(messageInTopic, times(1)).sendMessage(Matchers.any(), Msg.SAVE);
但这会起作用:
verify(messageInTopic, times(1)).sendMessage(Matchers.any(), Matchers.eq(Msg.SAVE));
另外,作为第二个仅供参考,有许多不同的方法来验证参数。这是一篇包含所有不同方式信息的帖子:Mockito。验证方法参数。如果您想验证对象参数,这一点尤其重要。