jeudi 2 juillet 2015

Structuring test code

Currently we are trying to implement some unittesting on our services. In the below service an order is created and a audit registration is made about the creation of an order. When writing the two tests (because we think the tests should be seperated to get tests with 1 responsibility) this was where I started with:

public class TestPacklineOrderManagementService
{

    [Fact]
    public void CreateNewProductWhenNoPacklineOrderIsAvailable()
    {

        IPackLineOrderRepository packLineOrderRepository = Substitute.For<IPackLineOrderRepository>();
        packLineOrderRepository.GetActive(Arg.Any<PackLine>()).Returns(x => null);
        var rawProductRepository = Substitute.For<IRawProductRepository>();
        rawProductRepository.Get(1).Returns(new RawProduct {Id = 1});
        var packlineRepository = Substitute.For<IPackLineRepository>();
        packlineRepository.Get(1).Returns(new PackLine {Id = 1});
        var auditRegistrationService = Substitute.For<IAuditRegistrationService>();
        var packlineOrderManagementService = new PacklineOrderManagementService(packLineOrderRepository, rawProductRepository, packlineRepository, auditRegistrationService);

        packlineOrderManagementService.SetProduct(1,1);

        packLineOrderRepository.Received()
            .Insert(Arg.Is<PackLineOrder>(x => x.PackLine.Id == 1 && x.Product.Id == 1));
    }

    [Fact]
    public void AuditCreateNewProductWhenNoPacklineOrderIsAvailable()
    {
        IPackLineOrderRepository packLineOrderRepository = Substitute.For<IPackLineOrderRepository>();
        packLineOrderRepository.GetActive(Arg.Any<PackLine>()).Returns(x=>null);
        var rawProductRepository = Substitute.For<IRawProductRepository>();
        rawProductRepository.Get(1).Returns(new RawProduct { Id = 1 });
        var packlineRepository = Substitute.For<IPackLineRepository>();
        packlineRepository.Get(1).Returns(new PackLine { Id = 1 });
        var auditRegistrationService = Substitute.For<IAuditRegistrationService>();
        var packlineOrderManagementService = new PacklineOrderManagementService(packLineOrderRepository, rawProductRepository, packlineRepository, auditRegistrationService);

        packlineOrderManagementService.SetProduct(1, 1);

        auditRegistrationService.Received()
            .Audit(Arg.Is<PackLineOrderAudit>(item => item.Action == PackLineOrderAction.CreatePacklineOrder));
    }
}

As you can see a lot of duplicate code. To prevent this I tried to refactor this and it resulted in the code below:

public class TestPacklineOrderManagementService2
{

    [Fact]
    public void CreateNewProductWhenNoPacklineOrderIsAvailable()
    {
        IPackLineOrderRepository packLineOrderRepository;
        IAuditRegistrationService auditRegistrationService;
        var packlineOrderManagementService = BuilderForCreateNewProductWhenNoPacklineOrderIsAvailable(out packLineOrderRepository, out auditRegistrationService);

        packlineOrderManagementService.SetProduct(1,1);

        packLineOrderRepository.Received().Insert(Arg.Any<PackLineOrder>());
    }

    [Fact]
    public void AuditCreateNewProductWhenNoPacklineOrderIsAvailable()
    {
        IPackLineOrderRepository packLineOrderRepository;
        IAuditRegistrationService auditRegistrationService;
        var packlineOrderManagementService = BuilderForCreateNewProductWhenNoPacklineOrderIsAvailable(out packLineOrderRepository, out auditRegistrationService);

        packlineOrderManagementService.SetProduct(1, 1);

        auditRegistrationService.Received()
            .Audit(Arg.Is<PackLineOrderAudit>(item => item.Action == PackLineOrderAction.CreatePacklineOrder));
    }

    private PacklineOrderManagementService BuilderForCreateNewProductWhenNoPacklineOrderIsAvailable(out IPackLineOrderRepository packLineOrderRepository,
       out IAuditRegistrationService auditRegistrationService)
    {
        packLineOrderRepository = CreatePackLineOrderRepository(x => null);
        auditRegistrationService = CreateAuditRegistrationService();

        var rawProductRepository = CreateRawProductRepository(x => new RawProduct { Id = 1 });
        var packlineRepository = CreatePacklineRepository(x => new PackLine { Id = 1 });
        var packlineOrderManagementService = new PacklineOrderManagementService(packLineOrderRepository,
            rawProductRepository, packlineRepository, auditRegistrationService);

        return packlineOrderManagementService;
    }

    private IPackLineOrderRepository CreatePackLineOrderRepository(Func<CallInfo, PackLineOrder> getActiveResult)
    {
        IPackLineOrderRepository packLineOrderRepository = Substitute.For<IPackLineOrderRepository>();
        packLineOrderRepository.GetActive(Arg.Any<PackLine>()).Returns(getActiveResult);
        return packLineOrderRepository;
    }

    private IRawProductRepository CreateRawProductRepository(Func<CallInfo, RawProduct> getResult)
    {
        IRawProductRepository rawProductRepository = Substitute.For<IRawProductRepository>();
        rawProductRepository.Get(1).Returns(getResult);
        return rawProductRepository;
    }

    private IPackLineRepository CreatePacklineRepository(Func<CallInfo, PackLine> getResult)
    {
        IPackLineRepository packLineRepository = Substitute.For<IPackLineRepository>();
        packLineRepository.Get(1).Returns(getResult);
        return packLineRepository;
    }

    private IAuditRegistrationService CreateAuditRegistrationService()
    {
        return Substitute.For<IAuditRegistrationService>();
    }
}

Is there any way to get a better code base for our unittests?

Aucun commentaire:

Enregistrer un commentaire