🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Introduction
The doThrow() method in Mockito is used to specify that a method call on a mock object should throw an exception. This is particularly useful when you want to test how your code handles exceptions from dependencies. This tutorial will demonstrate how to use the doThrow() method in Mockito to configure mock objects to throw exceptions.
Maven Dependencies
To use Mockito with JUnit 5, add the following dependencies to your pom.xml file:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Example Scenario
We will create a BankService class that has a dependency on a BankRepository. Our goal is to test how the BankService handles exceptions thrown by the BankRepository using the doThrow() method in Mockito.
BankService and BankRepository Classes
First, create the Account class, the BankRepository interface, and the BankService class.
public class Account {
private String accountNumber;
private double balance;
// Constructor, getters, and setters
public Account(String accountNumber, double balance) {
this.accountNumber = accountNumber;
this.balance = balance;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
public interface BankRepository {
Account findAccountByNumber(String accountNumber) throws Exception;
void withdraw(String accountNumber, double amount) throws Exception;
}
public class BankService {
private final BankRepository bankRepository;
public BankService(BankRepository bankRepository) {
this.bankRepository = bankRepository;
}
public Account getAccountDetails(String accountNumber) throws Exception {
return bankRepository.findAccountByNumber(accountNumber);
}
public void withdrawAmount(String accountNumber, double amount) throws Exception {
bankRepository.withdraw(accountNumber, amount);
}
}
JUnit 5 Test Class with Mockito
Create a test class for BankService using JUnit 5 and Mockito.
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class BankServiceTest {
@Mock
private BankRepository bankRepository;
@InjectMocks
private BankService bankService;
@Test
public void testGetAccountDetails() throws Exception {
// Given
String accountNumber = "12345";
Account account = new Account(accountNumber, 1000.0);
when(bankRepository.findAccountByNumber(accountNumber)).thenReturn(account);
// When
Account result = bankService.getAccountDetails(accountNumber);
// Then
assertNotNull(result);
assertEquals(accountNumber, result.getAccountNumber());
assertEquals(1000.0, result.getBalance());
}
@Test
public void testWithdrawAmountThrowsException() {
// Given
String accountNumber = "12345";
doThrow(new Exception("Insufficient funds")).when(bankRepository).withdraw(accountNumber, 500.0);
// When & Then
Exception exception = assertThrows(Exception.class, () -> {
bankService.withdrawAmount(accountNumber, 500.0);
});
assertEquals("Insufficient funds", exception.getMessage());
}
}
Explanation
Creating Mocks with
@Mock:- The
@Mockannotation creates a mock instance of theBankRepositoryinterface. This mock instance can be used to simulate the behavior of theBankRepositoryin a controlled way.
- The
Injecting Mocks with
@InjectMocks:- The
@InjectMocksannotation injects the mockBankRepositoryinto theBankServiceinstance to provide a controlled test environment. This allows theBankServicemethods to be tested in isolation from the actualBankRepositoryimplementation.
- The
Configuring Mock Behavior with
doThrow():- The
doThrow(new Exception("Insufficient funds")).when(bankRepository).withdraw(accountNumber, 500.0);method configures the mockBankRepositoryto throw anExceptionwith the message "Insufficient funds" when thewithdrawmethod is called with the specified account number and amount. This allows thewithdrawAmountmethod of theBankServiceclass to be tested with controlled exception handling behavior from theBankRepository.
- The
Testing Configured Behavior:
- The
testWithdrawAmountThrowsException()method tests thewithdrawAmountmethod of theBankServiceclass. ThedoThrow()method ensures that the mockBankRepositorythrows the expected exception, allowing the exception-handling behavior of thewithdrawAmountmethod to be verified.
- The
Additional Scenarios
Scenario: Handling Different Exceptions
In this scenario, we will demonstrate how to configure different behaviors for a mock method using the doThrow() method.
@Test
public void testWithdrawAmountWithDifferentExceptions() {
// Given
String accountNumber = "12345";
doThrow(new IllegalArgumentException("Invalid amount")).when(bankRepository).withdraw(accountNumber, -100.0);
// When & Then
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
bankService.withdrawAmount(accountNumber, -100.0);
});
assertEquals("Invalid amount", exception.getMessage());
}
Explanation
Configuring Different Exceptions:
- The
doThrow(new IllegalArgumentException("Invalid amount")).when(bankRepository).withdraw(accountNumber, -100.0);method configures the mockBankRepositoryto throw anIllegalArgumentExceptionwith the message "Invalid amount" when thewithdrawmethod is called with the specified account number and negative amount. This allows thewithdrawAmountmethod of theBankServiceclass to be tested with different exception handling scenarios.
- The
Testing Configured Behaviors:
- The
testWithdrawAmountWithDifferentExceptions()method tests thewithdrawAmountmethod of theBankServiceclass with a different exception type to verify that the mockBankRepositorythrows the expected exception.
- The
Conclusion
The doThrow() method in Mockito simplifies the configuration of mock objects to throw exceptions for unit testing. By using doThrow(), you can easily define the behavior of mock methods when exceptions need to be tested, allowing you to verify the exception handling logic in your code. This step-by-step guide demonstrated how to effectively use the doThrow() method in your unit tests, covering different scenarios to ensure comprehensive testing of the BankService class.
Related Mockito Methods
Mockito mock()
Mockito spy()
Mockito when()
Mockito thenThrow()
Mockito verify()
Mockito times()
Mockito never()
Mockito any()
Mockito eq()
Mockito inOrder()
Mockito doReturn()
Mockito doThrow()
Mockito doAnswer()
Mockito timeout()
Mockito ArgumentMatchers
Comments
Post a Comment
Leave Comment