Тестируйте методы интерфейса Spring-Boot Repository, не касаясь базы данных, используя Mockito

2

У меня есть следующий тестовый класс:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class TransactionServiceTests {

    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Mock
    private MessagingService mockMessagingService;
    @Mock
    private CustomerRepository mockCustomerRepository;

    @Autowired
    TransactionService transactionService;

    @Test
    public void testTransactionBetweenCustomersAndBalanceOfReceiver() {

        int AMOUNT = 50;

        // prepare your test data unless you always expect those values to exist.
        Customer customerReceiver = new Customer();
        customerReceiver.setName("TestReceiver");
        customerReceiver.setBalance(12);
        mockCustomerRepository.save(customerReceiver);

        Customer customerSender = new Customer();
        customerSender.setName("TestSender");
        customerSender.setBalance(50);
        mockCustomerRepository.save(customerSender);

        int expectedReceiverAmount = customerReceiver.getBalance() + AMOUNT;
        int expectedSenderAmount = customerSender.getBalance() - AMOUNT;
        transactionService.makeTransactionFromSenderToReceiver(customerSender, customerReceiver, AMOUNT);

        assertEquals(expectedSenderAmount, customerSender.getBalance());
        assertEquals(expectedReceiverAmount, customerReceiver.getBalance());

    }
}

Это TransactionService. сам класс:

@Service
public class TransactionService {

    private MessagingService messagingService;
    private CustomerRepository customerRepository;

    private static final Logger log = LoggerFactory.getLogger(TransactionService.class);

    @Autowired
    public TransactionService(MessagingService messagingService, CustomerRepository customerRepository){
        Assert.notNull(messagingService, "MessagingService cannot be null");
        this.messagingService = messagingService;
        Assert.notNull(customerRepository, "CustomerRepository cannot be null");
        this.customerRepository = customerRepository;
    }

    public void makeTransactionFromSenderToReceiver(Customer sender, Customer receiver, int amount) {

        if (sender.getBalance() >= amount) {
            sender.setBalance(sender.getBalance() - amount);
            receiver.setBalance(receiver.getBalance() + amount);

            customerRepository.save(sender);
            customerRepository.save(receiver);
        }

        else {    
            throw new RuntimeException();
        }
    }
}

Во время теста он добавляет вышеупомянутых пользователей в мою живую базу данных и оставляет их там даже после завершения тестов. Могу ли я каким-то образом сказать Mockito не касаться моей базы данных? Или это совершенно невозможно?

  • 2
    То, что вы определяете фиктивный экземпляр в тесте, не означает, что все объекты начнут использовать этот фиктивный экземпляр. Вам необходимо внедрить фиктивный репозиторий в тестируемую службу. Забудьте о SpringJUnit4ClassRunner для модульного тестирования. Просто используйте new TransactionService(mockMessagingService, mockCustomerRepository) .
  • 0
    Кроме того, вызов mockCustomerRepository.save(customerReceiver);mockCustomerRepository.save(customerReceiver); из теста не имеет особого смысла. Чего ты пытаешься достичь?
Показать ещё 1 комментарий
Теги:
spring-boot
mockito

2 ответа

3
Лучший ответ

"Mock" вызовы метода репозитория. Кроме того, используйте @InjectMocks вместо @Autowired для TransactionService. И вы также можете использовать MockitoJUnitRunner. Как издеваться над вызовами репозитория:

when(customerRepository.save(sender)).thenReturn(someSenderInstance);

Чтобы проверить, вызван ли вызов издеваемого метода, используйте:

verify(customerRepository, times(1)).save(sender);

Кроме того, помните одно: вы испытываете услуги! Поэтому все обращения к базе данных должны быть издевательскими.

  • 0
    Спасибо! Теперь все работает как нужно!
1

Как было предложено JB Nizet, только потому, что вы определяете фиктивный экземпляр в тесте, не означает, что все объекты начнут использовать этот макет. Чтобы достичь такого поведения, которое вы хотите достичь, вам нужно использовать @InjectMocks в тестируемом классе, который в вашем случае является TransactionService. Чтобы понять разницу между @Mock и @InjectMocks, обратитесь к этому вопросу разницы между @Mock и @InjectMocks

Ещё вопросы

Сообщество Overcoder
Наверх
Меню