Sprint Challenge: Library Service
Overview
In this Sprint Challenge, you'll apply the patterns and practices you've learned throughout the sprint to build a Library Service. This challenge will test your understanding of dependency injection, test-driven development, and mocking techniques.
You'll build a service that manages books, patrons, and borrowing functions, with a focus on maintainable, testable code.
Challenge Requirements
Your task is to implement a Library Service with the following components:
- Book Repository - For storing and retrieving book information
- Patron Repository - For storing and retrieving patron information
- Borrowing Service - For managing the borrowing and returning of books
- Notification Service - For sending notifications about due dates, overdue books, etc.
You'll use dependency injection to create a loosely coupled design, and you'll write tests for each component using TDD and mocking techniques.
Core Requirements
1. Dependency Injection
- Use constructor-based dependency injection
- Define interfaces for all repositories and services
- Ensure your service implementations depend on interfaces, not concrete implementations
2. Test-Driven Development
- Write tests before implementing the functionality
- Follow the red-green-refactor cycle
- Achieve high test coverage for your business logic
3. Mocking
- Use Mockito to mock dependencies in your tests
- Verify interactions between components
- Use argument captors where appropriate
Functional Requirements
- Book Management
- Add new books to the library
- Find books by ID, title, or author
- Update book information
- Remove books from the library
- Patron Management
- Register new patrons
- Find patrons by ID or name
- Update patron information
- Deactivate patron accounts
- Borrowing System
- Check out books to patrons
- Return books to the library
- Track due dates for borrowed books
- Handle overdue books and fines
- Notification System
- Send checkout confirmations
- Send due date reminders
- Send overdue notifications
Example Code Structure
// Interfaces
public interface BookRepository {
Book findById(String id);
List findByTitle(String title);
List findByAuthor(String author);
void save(Book book);
void delete(String id);
}
public interface BorrowingService {
BorrowingReceipt borrowBook(String patronId, String bookId);
ReturnReceipt returnBook(String patronId, String bookId);
List getBorrowedBooks(String patronId);
List getOverdueBooks();
}
// Implementation with dependency injection
public class BorrowingServiceImpl implements BorrowingService {
private final BookRepository bookRepository;
private final PatronRepository patronRepository;
private final NotificationService notificationService;
public BorrowingServiceImpl(
BookRepository bookRepository,
PatronRepository patronRepository,
NotificationService notificationService
) {
this.bookRepository = bookRepository;
this.patronRepository = patronRepository;
this.notificationService = notificationService;
}
@Override
public BorrowingReceipt borrowBook(String patronId, String bookId) {
// Implementation...
}
// More methods...
}
// Test using TDD and mocking
@Test
public void shouldNotAllowBorrowingUnavailableBook() {
// Arrange
BookRepository mockBookRepo = mock(BookRepository.class);
PatronRepository mockPatronRepo = mock(PatronRepository.class);
NotificationService mockNotification = mock(NotificationService.class);
Book unavailableBook = new Book("123", "Test Book", "Author");
unavailableBook.setAvailable(false);
Patron patron = new Patron("456", "Test Patron");
when(mockBookRepo.findById("123")).thenReturn(unavailableBook);
when(mockPatronRepo.findById("456")).thenReturn(patron);
BorrowingService service = new BorrowingServiceImpl(
mockBookRepo, mockPatronRepo, mockNotification);
// Act & Assert
assertThrows(BookUnavailableException.class, () -> {
service.borrowBook("456", "123");
});
verify(mockBookRepo).findById("123");
verify(mockPatronRepo).findById("456");
verify(mockNotification, never()).sendBorrowingConfirmation(any(), any());
}
Submission Requirements
- Clone the starter repository from GitHub Classroom
- Implement all the required functionality
- Ensure all tests pass
- Submit your solution through GitHub Classroom by the deadline