Testing legacy troubles

@konrad_126

LEgacy code?

No tests.

THE CASE OF AN IRRITATING PARAMETER

<?php

class CalculatePrice
{
	public function __construct(private VatDotComClient $vatProvider)
	{
	}

	public function calculate(Product $product) : float
	{
		$taxRate = $this->vatProvider->getRate($product->countryCode());
		// some business logic to calculate price
	}
}
<?php

class CalculatePriceTest
{
      public function itAppliesTheTaxRate()
      {
          $calculateTax = new CalculatePrice(
              new VatDotComClient('api-key', 'secret')
          );
              // ...
      }
}
<?php

class CalculatePriceTest
{
      public function itAppliesTheTaxRate()
      {
         // ...
      }
      
      public function itAppliesDiscount()
      {
         // ...
      }

      public function itAppliesVoucher()
      {
         // ...
      }

}

vat.com

<?php

class CalculatePriceTest
{
      public function itAppliesTheTaxRate()
      {
         // ...
      }
      
      public function itAppliesDiscount()
      {
         // ...
      }

      public function itAppliesVoucher()
      {
         // ...
      }

}

dummy VAT provider

<?php

class CalculatePrice
{
	public function __construct(private VatDotComClient $vatProvider)
	{
	}

	public function calculate(Product $product)
	{
		$taxRate = $this->vatProvider->getRate($product->countryCode());
		// some business logic to calculate price
	}
}
<?php

interface VatProvider
{
	public function getRate(string $countryCode): float;
}

Extract Interface

<?php

class CalculatePrice
{
	public function __construct(private VatProvider $vatProvider)
	{
	}

	public function calculate(Product $product)
	{
		$taxRate = $this->vatProvider->getRate($product->countryCode());
		// some business logic to calculate price
	}
}
<?php

class TestProvider implements VatProvider
{
	public function __construct(private float $rate)
	{
	}

	public function getRate(string $countryCode)
	{
		return $this->rate;
	}
}
<?php

public function itAppliesTheTaxRate()
{
	$calculateTax = new CalculatePrice(
		new TestProvider(0.25)
	);

	// ... Assert price what expected (with 0.25 tax rate)
}

THE CASE

 HIDDEN DEPENDENCY

<?php

class ProcessPayment
{
	public function __construct()
	{
		// ...
	}

	public function process(Payment $payment)
	{
		// ...
	}
}
<?php

public function itRecordsThePayment()
{
	$payment = new Payment(340, 'EUR', 12);

	$processPayment = new ProcessPayment();
	$processpayments->process($payment);
	
	// ... Assert stuff
}
<?php

class ProcessPayment
{
	public function __construct()
	{
		// some code
		$this->mailer = new Mailer('api-key', 'secret');
		// some code
	}

	public function process(Payment $payment)
	{
		// ...
	
		$this->mailer->send(
        		$payment->receiver(), 
        		new PaymentNotificationMessage($payment)
        	);
		
	}
}
<?php

class ProcessPayment
{
	public function __construct()
	{
		$this->mailer = new Mailer('api-key', 'secret');
	}

	public function process(Payment $payment)
	{
		// ...
	}
}
<?php

class ProcessPayment
{
	public function __construct(Mailer $mailer)
	{
		$this->mailer = $mailer;
	}

	public function process(Payment $payment)
	{
		// ...
	}
}

Parameterize Constructor

(Extract Interface)

DESIGN?

dependency injection principle

strategy design pattern

depend on abstract not a concrete

More advice?

THANK YOU

@konrad_126

Testing Legacy Troubles

By konrad 126

Testing Legacy Troubles

  • 242