Symfony Unit Testing
Published: 2022-04-15 10:17:37

In order to unit test in Symfony, we need to install symfony's test-pack first:

```
$ composer require --dev symfony/test-pack
```

Check if install succeed by running PHPUnit:

```
$ php bin/phpunit
```

If you are running your project in a docker container, make sure you run this command in your container.

```
$ docker exec -it [enter_container_name] php bin/phpunit
```

If everything went well, you should receive the message **"No tests executed!"**

# Write your first test

Create your first test "FirstTest.php" and place it in the directory "tests" of the root of your project:

```
<?php

namespace Api\Tests;

use PHPUnit\Framework\TestCase;

class FirstTest extends TestCase
{
    public function testEquals() {
        $actual = 1;
        $expected = 1;

        $this->assertEquals($expected, $actual);
    }
}
```

As you can see this class extends from TestCase, which is needed to initiate a PHPUnit test. In this test we test if the $actual and $expected are equals.

Now try and run this test to see what happens:

```
$ php bin/phpunit
```

The result should be something like **"OK (1 test, 1 assertion)"**

Congrats! You just wrote your very first PHPUnit test.

# What to test?

This is great, but how can I apply this to my code? Great question, lets check this out.

Firstly, we'll create a controller so we can test the outcome of our method:

```
<?php

namespace Api\Controller;

class Calculator
{
    public function add ($a, $b) {
        return $a + $b;
    }
}
```

The naming convention for a test exists of "Controller + Test" used in CamelCase. So ours will be CalculatorTest. The method itself exist of "test + Method". Like so:

```
<?php

namespace Api\Tests;

use Api\Controller\Calculator;
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    public function testAdd() {
        $calculator = new Calculator();
        $actual = $calculator->add(1,2);

        $expected = 3;

        $this->assertEquals($expected, $actual);
    }
}
```

As you can see, we've initiated a Calculator object and added the numbers 1 and 2 as $actual result. My $expected result is an outcome of 3. If we run this test `$ php bin/phpunit` we'll see our test runs successfully **"OK (1 test, 1 assertion)"**.

# Why to test

Now lets say after a couple of months your colleague gets the question to change your method because of whatever reason. He or she changed it to always add +10:

```
<?php

namespace Api\Controller;

class Calculator
{
    public function add ($a) {
        return $a + 10;
    }
}
```

If we run our test again now `$ php bin/phpunit`, we'll get exactly what we want. An error:

**"FAILURES! Tests: 1, Assertions: 1, Failures: 1."**.

So our colleague knows he changed something what shouldn't be changed or he needs to refactor our test and probably more code elsewhere.

# Bonus

If you write tests before you write the actual code itself, this would be a great practice for Test Driven Development (TDD). A great way to think before coding and ensure the quality of your code.

Couple of asserts I like to use are:
1. $this->assertEquals($expected, $actual);
2. $this->assertTrue($argument);
3. $this->assertInstanceOf(Object::class, $object);
4. $this->assertSame($expected, $actual);
5. $this->assertFalse($argument);

Hope this helps!