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