简体   繁体   中英

Test Spring-Boot Repository interface methods without touching the database using Mockito

I have the following test class:

@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());

    }
}

This is the TransactionService . class itself:

@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();
        }
    }
}

During the test, it is adding the above mentioned users to my live database and leaving them there even after the tests are finished. Can I in some way tell Mockito to not touch my database? Or is that totally not possible?

"Mock" your repository method calls. Also, use @InjectMocks instead @Autowired for TransactionService . And you can also use MockitoJUnitRunner . How to mock repository calls:

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

To verify that mocked method call has been invoked use:

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

Also, remember one thing: You are testing services! Therefore, all calls to database should be mocked.

As suggested by JB Nizet, just because you define a mock instance in a test doesn't mean all objects will start using that mock instance. To achieve the behaviour you want to achieve, you need to use @InjectMocks on the class you are testing which in your case is TransactionService. To understand the difference between @Mock and @InjectMocks , refer to this question difference between @Mock and @InjectMocks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM