DEV Community

Sam Ferree
Sam Ferree

Posted on

How to avoid mocking repository for Unit Tests

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;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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)