023: End to End Testing REST API

In this episode we continue to use Test Driven Development (TDD) to drive out the implementation the simple HTTP REST(ish) API microservice in PHP.

We add handling when the database is not available to the endpoint GET to retrieve a book by its ISBN.

We start by refactoring the endpoint code to add different layers (Controller – Business Logic – Book Repository). We then add Unit and Integration tests to ensure our code ensure each part of our application can handle the different exceptions being thrown.

The code produced during this episode can be found on GitHub

During this video we use:

022: End to End & Integration testing REST API

In this episode we continue to use Test Driven Development (TDD) to drive out the implementation the simple HTTP REST(ish) API microservice in PHP.

We add handling when a book is not available to the endpoint GET to retrieve a book by its ISBN.

Starting with an End to End Test write using PHP Unit and Guzzle HTTP Client for PHP to design out how consumers of the API will interact with the endpoint.
We then add an Integration test to ensure our code uses Doctrine PHP ORM to interact with the Postgres database to get the book data.

The code produced during this episode can be found on GitHub

During this video we use:

Episode 021: End to End & Integration Testing a REST API

In this episode we continue to use Test Driven Development (TDD) to drive out the implementation the simple HTTP REST(ish) API microservice in PHP.

We add a new endpoint GET to retrieve a book by its ISBN.

Starting with an End to End Test write using PHP Unit and Guzzle HTTP Client for PHP to design out how consumers of the API will interact with the endpoint.
We then add an Integration test to ensure our code uses Doctrine PHP ORM to interact with the Postgres database to get the book data.

Finally we add a Unit Test to the Book object to enable it to render itself into JSON using PHP’s JsonSerializable interface.

Don’t miss the excellent demonstration why we need to use different types of test at 33.15 the moment all the Unit Tests pass and the End to End Tests still fails

The code produced during this episode can be found on GitHub

Doctrine Entity Event

In my first post on Single Table Inheritance I had some example code that made use of a $tax variable to demonstrate where tax is added or removed. This simplification hides some complexity of the actual implementation.

In the actual implementation I needed to have access to a TaxCalculator object in all Price entities. The issue I had was how to ensure this happens without having to remember to manually inject the TaxCalculator everywhere Price entities are retrieved or persisted.

To do this I used a Doctrine feature called Entity Listeners. The Listener functionality allows you to access entities during a number of Doctrine operations.  Once configured you are able to hook into a number of different events before or after various CRUD events, they are:

  • preFlush
  • postLoad
  • PrePersist
  • PostPersist
  • PreUpdate
  • PostUpdate
  • PostRemove
  • PreRemove

The listening function is passed the entity that triggering the event and an instance of Doctrine\Common\EventArgs. In my example i do not use the EventArgs object. It can be used to give you another way to access the entity triggering the event or an instance of Doctrine/ORM/EntityManager.

The following Doctrine YAML configuration specifies the Entity Event Listener class (Braddle\EntityListener) for the Price entities.

Braddle\Entity\Price:
  type: entity
  table: price
  inheritanceType: SINGLE_TABLE
  discriminatorColumn:
    name: type
    type: string
  discriminatorMap:
    including_tax: PriceIncludingTax
    excluding_tax: PriceExcludingTax
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    price:
      type: float
  entityListeners:
    Braddle\EntityListener:

Here is the implementation of my Entity Event Listener (Braddle\EntityListener) this listener injects a TaxCalculator into price entities. I have only used the postLoad and postPersist functions so that i can ensure that new Prices have a TaxCalculator injected when they are saved and all existing Prices when they are retrieved from the database.

namespace Braddle;

use Braddle\Entity\Price;

class EntityListener
{

    /**
     * Fired before an object is about to be saved by doctrine
     *
     * @param PricingConfigAware $object The model to inject the price config into
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     *
     * @return void
     */
    public function prePersist(Price $object)
    {
        $object->setTaxCalculator($this->getTaxCalculator());
    }

    /**
     * Fired before an object is about to be saved by doctrine
     *
     * @param PricingConfigAware $object The model to inject the price config into
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     *
     * @return void
     */
    public function postLoad(Price $object)
    {
        $object->setTaxCalculator($this->getTaxCalculator());
    }

    /**
     * @return \Braddle\TaxCalculator
     */
    private function getTaxCalculator()
    {
        return new TaxCalculator(20);
    }
}

You can find the full example application using the Doctrine Entity Event in this GitHub Repository.

Class Table Inheritance

The Class Table Inheritance feature of Doctrine allows you to have a number of different entities similar to Single Table Inheritance. The difference with Class Table Inheritance is it allows you to split the data specific to an entity in to a separate table. This allows each entity to have extra data specific to its needs, without having a table with a large number of null-able columns.

When creating a new entity you simply instantiate the class for the specific type required. When you persist the entity Doctrine creates an entry in the base table with the discriminator of your chosen class, Doctrine will also create an entry in the class specific table with a foreign key linking back to the base table.

When retrieving a specific entity from the database Doctrine uses the discriminator to decide which class to construct the data with. Doctrine also loads any class specific data from the class specific table.

If I were implement an Order Item system using Class Table Inheritance, I would create an abstract class and base table that could handle all of the generic Order Item functionality and data. Creating a concrete implementations for each specific Order Items requirements.

In the example configuration I have only created two concrete implementations one for products and one for vouchers.

# Model.Order.OrderItem.yml
Model\Order\OrderItem:
  type: entity
  inheritanceType: JOINED
  discriminatorColumn:
    name: type
    type: string
  discriminatorMap:
    product_order_item: ProductOrderItem
    voucher_order_item: VoucherOrderItem
  table: order_item
  id:
    id:
      type: integer
      generator:
        strategy: TODO
  fields:
    createdAt:
        type: datetime
  manyToOne:
    order:
      targetEntity: Model\Order\Order
      inversedBy:   orderItems
      joinColumn:
        name:                 order_id
        referencedColumnName: id
        
# Model.Order.ProductOrderItem.yml
Model\Order\ProductOrderItem:
  type: entity
  fields:
    sku:
      type:     string
      nullable: false
    quantity:
      type:     integer
      nullable: false
      
# Model.Order.VoucherOrderItem.yml
Model\Order\VoucherOrderItem:
  type: entity
  fields:
    voucherCode:
      type:     string
      nullable: false
    discountAmount:
      type:     float
      nullable: false

With the above configuration I would then create the classes below.

An abstract OrderItem that handles the link between OrderItems and their Orders and also maintains the time that an OrderItem was created.

class OrderItem
{

    /**
     * @var integer
     */
    private $id;

    /**
     * @var Order
     */
    private $order;

    /**
     * @var \DateTime
     */
    private $createdAt;

    public function __construct(Order $order)
    {
        $this->order     = $order;
        $this->createdAt = new \DateTime();
    }
}

The concrete ProductOrderItem extends the OrderItem with functionality specific to Products within an Order. Storing and validating the products Sku and required quantity.

class ProductOrderItem extends OrderItem
{

    /**
     * @var string
     */
    private $sku;

    /**
     * @var integer
     */
    private $quantity;

    public function setSku($sku) { ... }
    public function getSku() { ... }

    public function setQuantity($quantity) { ... }
    public function getQunatity() { ... }
}

The concrete VoucherOrderItem extends the OrderItem with functionality specific to Vouchers within an Order. storing and validating the voucher code and discount amount.

class VoucherOrderItem extends OrderItem
{

    /**
     * @var string
     */
    private $voucherCode;

    /**
     * @var float
     */
    private $discountAmount

    public function setVoucherCode($voucherCode) { ... }
    public function getVOcuherCode() { ... }


    public function setDiscountAmount($discountAmount) { ... }
    public function getDiscountAmount() { ... }
}

This implementation of the OrderItems maintains a clean database without any unecessary null-able columns. The implementation also conforms to the Single Responsibility Principle as a concrete OrderItem class only needs to be edited if the requirements of that specific type of OrderItem change. If I needed to create a new OrderItem for employee discount, I would create and configure a new EmployeeDiscountOrderItem entity in Doctrine without having to touch any existing OrderItem classes.

Single Table Inheritance

The Doctrine single table inheritance feature maps a number of different entity classes to a single table in your database.

When creating an entity you simple construct the desired class. When you persist the new entity to your data store, Doctrine stores the discriminator (class type identifier) with the rest of the entity’s data.

When retrieving a specific entity from the database Doctrine uses a discriminator to decide which class to construct with the data.

I have recently used the single table inheritance feature to refactor a Price class that used to use a boolean field to determine if the price contained within the entity was inclusive or exclusive of tax.

The previous code that made use of the Price entity looked something like this

$price = $priceRepository->findById(1);

$priceWithTax = null;

if ($price->isTaxIncluded()) {
    $priceWithTax = $price->getPrice();
} else {
    $priceWithTax = $price->getPrice() + $tax;
}

This code is difficult to init test this calling code given the number of routes through it.

However if we use single table inheritance we can refactor out the conditionals for Polymorphism.

Before I started to refactor the functionality the entity’s configuration YAML looked something like this

Slapi\Model\Product\Price\Price:
  type: entity
  table: price
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    price:
      type: float
    taxIncluded:
      type: boolean

I then changed the YAML set up to something similar to this

# Model.Price.Price.yml
Model\Price\Price:
  type: entity
  table: price
  inheritanceType: SINGLE_TABLE
  discriminatorColumn:
    name: type
    type: integer
  discriminatorMap:
    including_tax: IncludingTax
    excluding_tax: ExcludingTax
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    price:
      type: float

# Model.Price.IncludingTax.yml
Model\Price\IncludingTax:
  type: entity

# Model.Price.ExcludingTax.yml
Model\Price\ExcludingTax:
  type: entity

The new configuration gives us the following classes.

class price
{
    /**
     * @var float
     */
    private $price;

    /**
     * @return float
     */
    abstract public function getPrice();
}
class ExcludingTax extends Price
{
    /**
     * @return float
     */
    public function getPrice()
    {
        return $this->price + $tax;
    }
}
class IncludingTax extends Price
{
    /**
     * @return float
     */
    public function getPrice()
    {
         return $this->price;
    }
}

After the refactoring the entity to use single table inheritance to create a PriceIncludingTax and PriceExcludingTax class the code makes use of the price entities now looks something like this

$price = $priceRepository->findById(1);

$priceWithTax =  $price->getPrice();

The code in the second example is much easier to read and has no knowledge of the fact that a price entity return from the price repository could be inclusive or exclusive of tax. The calling code is also a lot easier to unit test as there is now only a single route through it.

Inheritance in Doctrine

I was discussing a feature of Doctrine that allows you to map object inheritance in entities. I have used this feature a number of times for a few different scenarios. I was very surprised that none of the other developers had used the feature before and a few had not even heard of it.

I thought it would be useful to discuss how I have used this feature to implement a clean design recently.

The feature has three different modes of working Single Table Inheritance, Class Table Inheritance and Mapped Superclass (which i have not used yet).