如何使用mockito验证是否使用此参数或另一个参数调用了特定方法?

问题描述 投票:0回答:1

如何使用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 参数。

请问如何进行此测试?

java unit-testing junit mockito tdd
1个回答
0
投票

@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

  1. assertEquals
    失败,因为
    customerEntity
    customer
    不匹配。
  2. 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。验证方法参数。如果您想验证对象参数,这一点尤其重要。

© www.soinside.com 2019 - 2024. All rights reserved.