I commonly see code written like this, even in courses.
public class DeskBookingProcessor
{
public readonly IBookingRepository _bookingRepository;
public readonly int _capacity;
public async Task<Booking?> Book(BookingRequest request)
{
var currentBookings = await _bookRepository.GetBookingsAsync(request.Date);
if (currentBookings + 1 > _capacity)
{
return null;
}
else
{
var booking = new Booking(request);
await _bookingRepository.SaveAsync(booking);
return booking;
}
}
}
The drawback is you have to mock a whole IBookingRepository (Even the methods this feature doesn't use) to test your booking logic.
Alternatively, you could do this
public class BookingAgent
{
public Booking? Book(BookingRequest request, int currentBookings, int capacity) =>
currentBookings + 1 > capacity
? null
: new Booking(request);
}
public class DeskBookingProcessor
{
public readonly IBookingRepository _bookingRepository;
public readonly int _capacity;
public async Task<Booking?> Book(BookingRequest request)
{
// Impure Collect
var currentBookings = await _bookRepository.GetBookingsAsync(request.Date);
var agent = new BookingAgent();
// Pure Calculation
var booking = agent.Book(request, currentBookings.Count(), capacity);
// Impure Commit
if (booking != null) await _bookRepository.SaveBookingAsync(booking);
return booking;
}
}
Now your unit tests don't need to mock impure dependencies, just test the BookingAgent by passing the parameters.
Leave it to your integration tests flex the combination of the pure logic and impure dependencies. Prefer the kind that stand up a whole test server and send HTTP requests and check HTTP responses.
That is all.
Top comments (0)