🎓 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
Behavior-Driven Development (BDD) encourages writing tests in a more natural, readable language that describes the behavior of the application. Mockito provides the BDDMockito class, which allows you to use BDD-style syntax for stubbing and verifying interactions. This tutorial will demonstrate how to use BDDMockito to write more readable and expressive tests.
Maven Dependencies
To use Mockito with JUnit 5 and enable BDDMockito syntax, 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 LibraryService class that has a dependency on a BookRepository. Our goal is to test the LibraryService methods using BDDMockito to handle stubbing and verifying interactions.
LibraryService and BookRepository Classes
First, create the Book class, the BookRepository interface, and the LibraryService class.
public class Book {
private String title;
private String author;
// Constructor, getters, and setters
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
public interface BookRepository {
void saveBook(Book book);
Book findBookByTitle(String title);
List<Book> findAllBooks();
}
public class LibraryService {
private final BookRepository bookRepository;
public LibraryService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
public void addBook(String title, String author) {
Book book = new Book(title, author);
bookRepository.saveBook(book);
}
public Book getBookByTitle(String title) {
return bookRepository.findBookByTitle(title);
}
public List<Book> getAllBooks() {
return bookRepository.findAllBooks();
}
}
JUnit 5 Test Class with BDDMockito
Create a test class for LibraryService using JUnit 5 and BDDMockito.
import static org.mockito.BDDMockito.*;
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;
import java.util.Arrays;
import java.util.List;
@ExtendWith(MockitoExtension.class)
public class LibraryServiceTest {
@Mock
private BookRepository bookRepository;
@InjectMocks
private LibraryService libraryService;
@Test
public void testAddBook() {
// Given
String title = "Mockito in Action";
String author = "Ramesh Fadatare";
// When
libraryService.addBook(title, author);
// Then
then(bookRepository).should().saveBook(any(Book.class));
}
@Test
public void testGetBookByTitle() {
// Given
String title = "Mockito in Action";
Book book = new Book(title, "Ramesh Fadatare");
given(bookRepository.findBookByTitle(title)).willReturn(book);
// When
Book result = libraryService.getBookByTitle(title);
// Then
assertNotNull(result);
assertEquals(title, result.getTitle());
assertEquals("Ramesh Fadatare", result.getAuthor());
}
@Test
public void testGetAllBooks() {
// Given
Book book1 = new Book("Mockito in Action", "Ramesh Fadatare");
Book book2 = new Book("Effective Java", "Joshua Bloch");
List<Book> books = Arrays.asList(book1, book2);
given(bookRepository.findAllBooks()).willReturn(books);
// When
List<Book> result = libraryService.getAllBooks();
// Then
assertNotNull(result);
assertEquals(2, result.size());
assertEquals("Mockito in Action", result.get(0).getTitle());
assertEquals("Effective Java", result.get(1).getTitle());
}
@Test
public void testAddBookWithCustomMatcher() {
// Given
String title = "Mockito in Action";
String author = "Ramesh Fadatare";
// When
libraryService.addBook(title, author);
// Then
then(bookRepository).should().saveBook(argThat(book -> book.getTitle().equals("Mockito in Action") && book.getAuthor().equals("Ramesh Fadatare")));
}
}
Explanation
Creating Mocks with
@Mock:- The
@Mockannotation creates a mock instance of theBookRepositoryinterface. This mock instance can be used to simulate the behavior of theBookRepositoryin a controlled way.
- The
Injecting Mocks with
@InjectMocks:- The
@InjectMocksannotation injects the mockBookRepositoryinto theLibraryServiceinstance to provide a controlled test environment. This allows theLibraryServicemethods to be tested in isolation from the actualBookRepositoryimplementation.
- The
Using BDDMockito:
given(): Thegiven(bookRepository.findBookByTitle(title)).willReturn(book);method configures the mockBookRepositoryto return a specificBookobject when thefindBookByTitlemethod is called with the specified title.then(): Thethen(bookRepository).should().saveBook(any(Book.class));method verifies that thesaveBookmethod was called on theBookRepositorywith anyBookobject.argThat(): Thethen(bookRepository).should().saveBook(argThat(book -> book.getTitle().equals("Mockito in Action") && book.getAuthor().equals("Ramesh Fadatare")));method verifies that thesaveBookmethod was called on theBookRepositorywith aBookobject that matches the specified title and author.
Additional Scenarios
Scenario: Verifying No Interactions
In this scenario, we will demonstrate how to verify that no interactions occurred with the mock object using BDDMockito.
@Test
public void testNoInteractionsWithBookRepository() {
// Given
// No interactions expected
// When
// No method calls
// Then
then(bookRepository).shouldHaveNoInteractions();
}
Explanation
- Verifying No Interactions:
- The
then(bookRepository).shouldHaveNoInteractions();method verifies that no interactions occurred with theBookRepositorymock object. This ensures that theBookRepositorywas not used during the test.
- The
Scenario: Verifying Method Call Order
In this scenario, we will demonstrate how to verify the order of method calls using BDDMockito.
@Test
public void testMethodCallOrder() {
// Given
String title = "Mockito in Action";
Book book = new Book(title, "Ramesh Fadatare");
given(bookRepository.findBookByTitle(title)).willReturn(book);
// When
libraryService.addBook(title, "Ramesh Fadatare");
libraryService.getBookByTitle(title);
// Then
InOrder inOrder = inOrder(bookRepository);
then(bookRepository).should(inOrder).saveBook(any(Book.class));
then(bookRepository).should(inOrder).findBookByTitle(title);
}
Explanation
- Verifying Method Call Order:
- The
InOrder inOrder = inOrder(bookRepository);statement creates anInOrderobject to verify the order of interactions with theBookRepositorymock object. - The
then(bookRepository).should(inOrder).saveBook(any(Book.class));andthen(bookRepository).should(inOrder).findBookByTitle(title);methods verify that thesaveBookmethod was called before thefindBookByTitlemethod on theBookRepository.
- The
Conclusion
Using BDDMockito in Mockito allows you to write more readable and expressive tests that follow the Behavior-Driven Development (BDD) style. By using given(), then(), and other BDD-style methods, you can handle various scenarios and control the behavior of mock objects. This step-by-step guide demonstrated how to effectively use BDDMockito in your unit tests, covering different scenarios to ensure comprehensive testing of the LibraryService class.
Related Mockito BDDMockito Class Methods (Behavior-Driven Development Style)
Mockito BDDMockito
Mockito BDDMockito given()
Mockito BDDMockito willThrow()
Mockito BDDMockito willAnswer()
Mockito BDDMockito willReturn()
Mockito BDDMockito willDoNothing()
Mockito BDDMockito willCallRealMethod()
Mockito BDDMockito then()
Mockito BDDMockito.any()
Mockito BDDMockito.times()
Comments
Post a Comment
Leave Comment