Skip to main content
added 33 characters in body
Source Link
Matthew
  • 2k
  • 3
  • 19
  • 27

The three classes look something like:Current three classes

Extraction of behavior from current classes

The new class would look something similar to:Proposed new class using extracted behavior

The options I've come up with are:Questions about proposal

The three classes look something like:

The new class would look something similar to:

The options I've come up with are:

Current three classes

Extraction of behavior from current classes

Proposed new class using extracted behavior

Questions about proposal

Source Link
Matthew
  • 2k
  • 3
  • 19
  • 27

Unit testing and reusing extracted class

Currently I have 3 service classes, they all have a similar pattern, and I need to make a 4th service class which amalgamates the functionality of the other three.

The three classes look something like:

public class PersonService : IPersonService
{
    public PersonServiceResult CreatePerson(CreatePersonParams createPersonParams)
    {
        using (var unitOfWork = _unitOfWorkFactory.Create())
        {
            // [code]
            
            unitOfWork.Commit();
            return new PersonServiceResult(...);
        }
    }
}

public class OrderService : IOrderService
{
    public OrderServiceResult CreateOrder(
        int personId, 
        IEnumerable<PurchaseItem> items)
    {
        using (var unitOfWork = _unitOfWorkFactory.Create())
        {
            // [code]
            
            unitOfWork.Commit();
            return new OrderServiceResult(...);
        }
    }
}

public class PaymentProcessingService : IPaymentProcessingService
{
    public PaymentResult ProcessPayment(int orderId, CreditCard creditCard)
    {
        using (var unitOfWork = _unitOfWorkFactory.Create())
        {
            // [code]
            
            unitOfWork.Commit();
            return new PaymentResult(...);              
        }
    }
}

Now I have a need to use the behavior in all 3 of these classes into one unit-of-work, I still need the 3 other classes to exist for other dependecies in the project.

My first thought would be to extract a class for each one of the 3 services which takes a unit-of-work as an argument.

public class PersonCreator
{
    public CreatePersonResult CreatePerson(
        IUnitOfWork unitOfWork, 
        CreatePersonParams createPerson)
    {
        // [code]
    }
}

public class PersonService : IPersonService
{
    private readonly PersonCreator Creator = new PersonCreator();
            
    public PersonServiceResult CreatePerson(CreatePersonParams createPersonParams)
    {
        using (var unitOfWork = _unitOfWorkFactory.Create())
        {
            var result = Creator.CreatePerson(unitOfWork, createPersonParams);
            
            unitOfWork.Commit();
            return new PersonServiceResult(result);
        }
    }       
}

The new class would look something similar to:

public class QuickOrderService : IQuickOrderService
{
    private readonly PersonCreator PersonCreator = new PersonCreator(); 
    private readonly OrderCreator OrderCreator = new OrderCreator();    
    private readonly PaymentProcessor PaymentProcessor = new PaymentProcessor();    

    public QuickOrderResult CreateQuickOrder(
        CreatePersonParams createPersonParams,
        IEnumerable<PurchaseItem> items,
        CreditCard creditCard)
    {
        using (var unitOfWork = _unitOfWorkFactory.Create())
        {
            var person = PersonCreator.CreatePerson(unitOfWork, createPersonParams);
            var order = OrderCreator.CreateOrder(unitOfWork, person.Id, items);
            var payment = PaymentProcessor.Process(unitOfWork, order.Id, creditCard);
            
            unitOfWork.Commit();
            
            return QuickOrderResult(...);
        }
    }
}

This works fine, but I am concerned about testing this new class.

The options I've come up with are:

  1. Duplicate the majority of the tests for the QuickOrderService class
  2. Do not test this class as the majority of it is covered by other tests
  3. Inject PersonCreator, OrderCreator, and PaymentProcessor into QuickOrderService instead of instanciating them and just test that QuickOrderService calls the dependencies correctly

Though when doing this whole excersise it makes me think there may be a better solution that reduces duplication while retains code coverage.