Introduction
Many times developers try to test the 100% (or almost the 100%) of their code. Apparently, this is the aim every team should reach for their projects but, from my point of view, only one piece of the entire code should be fully tested: Your domain.
The domain is, basically, the part of your code which defines what the project actually does. For instance, when you persist an entity to the database, your domain is not in charge of persisting it on the database, but making sure that the persisted data makes sense according to your business model. Possibly, when you save your data on the database, you will use an external library like PHP Doctrine. This library is already fully tested, there is no need to test what it does. If you pass to doctrine the correct data, it will be saved to the database with no issues.
The example shown in the following sections does not try to show how the Domain Driven Design works, there are many articles which explain it very well. I will try to show how having your domain well defined and decoupled can help to test easily and focused on what your application does.
The example is built over a Symfony environment and using the PHPUnit library, but the idea is valid for any language or framework.
The code to test
Let’s imagine that our application connects to an external api which returns data about the rain probability for a specified date. The returned data looks like this:
{ "date" : "2022-12-01", "rain_probability" : 0.75 }
Now, we have to take those data and classify it following this mapping:
- rain_probability LOW
- rain_probability ≥ 0.40 && rain_probability MEDIUM
- rain_probability ≥ 0.75: HIGH
and save the result on a database table described by the following entity:
#[ORM\Entity(repositoryClass: RainMeasure::class)] class RainMeasure { #[ORM\Column] private string $date; #[ORM\Column] private float $probability; #[ORM\Column(length: 10)] private string $label; // Getters and setters // ....... }
Let’s create a handler which gets the external api data, sets the label according to the rain probability and saves it to the database.
class RainMeassureHandler { private EntityManagerInterface $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } public function saveMeasure(array $measureData): void { if($measureData['rain_probability'] = 0.40 && $measureData['rain_probability'] setDate($measureData['date']); $rainMeasure->setProbability($measureData['rain_probability']); $rainMeasure->setLabel($label); $this->em->persist($rainMeasure); $this->em->flush(); } }
If we try to create a test for the above handler, we will find that we will need to inject the EntityManagerInterface since the behaviour we want to test (setting a label according to the probability value) is coupled in the same handler which saves the result to the database. We could try to load the EntityManagerInterface using mocks and stubs but, is it necessary ?. Obviously not. As said before, we should try to focus on testing the behaviour that belongs to our domain, which is getting the correct label according to the rain probability.
Decoupling behaviour we want to test
In order to simplify our test, we are going to move the behaviour we want to test to another class:
class RainMeasureLabelHandler { public function getLabelFromProbability(float $prob): string { if($prob = 0.40 && $prob <p>And now, our RainMeassureHandler will look like this:</p> <pre class="brush:php;toolbar:false"> class RainMeasureHandler { private EntityManagerInterface $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } public function saveMeasure(array $measureData): void { $rainMeasureLabelHandler = new RainMeasureLabelHandler(); $label = $rainMeasureLabelHandler->getLabelFromProbability($measureData['rain_probability']); $rainMeasure = new RainMeasure(); $rainMeasure->setDate($measureData['date']); $rainMeasure->setProbability($measureData['rain_probability']); $rainMeasure->setLabel($label); $this->em->persist($rainMeasure); $this->em->flush(); } }
Now we can focus on test our RainMeasureLabelHandler which would be part of our domain and would have no dependencies to external layers. Testing it would be as easy as shown:
Conclusion
I would like to say that other kind of tests would be useful too. Maybe we have an api and we want to test input and outputs with a test environment which includes database and other resources we could need. But, remember to have your domain decoupled and fully tested.
The above is the detailed content of Focusing your tests on the domain. A PHPUnit example. For more information, please follow other related articles on the PHP Chinese website!

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP is not dying, but constantly adapting and evolving. 1) PHP has undergone multiple version iterations since 1994 to adapt to new technology trends. 2) It is currently widely used in e-commerce, content management systems and other fields. 3) PHP8 introduces JIT compiler and other functions to improve performance and modernization. 4) Use OPcache and follow PSR-12 standards to optimize performance and code quality.

The future of PHP will be achieved by adapting to new technology trends and introducing innovative features: 1) Adapting to cloud computing, containerization and microservice architectures, supporting Docker and Kubernetes; 2) introducing JIT compilers and enumeration types to improve performance and data processing efficiency; 3) Continuously optimize performance and promote best practices.

In PHP, trait is suitable for situations where method reuse is required but not suitable for inheritance. 1) Trait allows multiplexing methods in classes to avoid multiple inheritance complexity. 2) When using trait, you need to pay attention to method conflicts, which can be resolved through the alternative and as keywords. 3) Overuse of trait should be avoided and its single responsibility should be maintained to optimize performance and improve code maintainability.

Dependency Injection Container (DIC) is a tool that manages and provides object dependencies for use in PHP projects. The main benefits of DIC include: 1. Decoupling, making components independent, and the code is easy to maintain and test; 2. Flexibility, easy to replace or modify dependencies; 3. Testability, convenient for injecting mock objects for unit testing.

SplFixedArray is a fixed-size array in PHP, suitable for scenarios where high performance and low memory usage are required. 1) It needs to specify the size when creating to avoid the overhead caused by dynamic adjustment. 2) Based on C language array, directly operates memory and fast access speed. 3) Suitable for large-scale data processing and memory-sensitive environments, but it needs to be used with caution because its size is fixed.

PHP handles file uploads through the $\_FILES variable. The methods to ensure security include: 1. Check upload errors, 2. Verify file type and size, 3. Prevent file overwriting, 4. Move files to a permanent storage location.

In JavaScript, you can use NullCoalescingOperator(??) and NullCoalescingAssignmentOperator(??=). 1.??Returns the first non-null or non-undefined operand. 2.??= Assign the variable to the value of the right operand, but only if the variable is null or undefined. These operators simplify code logic, improve readability and performance.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

Atom editor mac version download
The most popular open source editor

Dreamweaver CS6
Visual web development tools

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function