Albertobeiz

Albertobeiz

Symfony Tips #10 - Test your Controllers

Symfony Tips #10 - Test your Controllers

Subscribe to my newsletter and never miss my upcoming articles

🖥 Symfony Tips: Quick and practical tricks to develop solid backend systems.

🥳 We made it! Now all the work we have done will pay off. See how simple our tests are:

class Post_SignUpUser_Test extends TestCase
{
    private Post_SignUpUser $useCase;
    private UserRepository $userRepository;
    private EmailService $emailService;
    private AnalyticsService $analyticsService;

    /**
     * @before
     */
    public function setup(): void
    {
        $this->userRepository = $this->createMock(UserRepository::class);
        $this->emailService = $this->createMock(EmailService::class);
        $this->analyticsService = $this->createMock(AnalyticsService::class);

        $this->useCase = new Post_SignUpUser(
            $this->userRepository,
            $this->emailService,
            $this->analyticsService
        );
    }

    public function testGivenUsedEmailThenThrowException()
    {
        $this->expectException(InvalidArgumentException::class);

        $this->userRepository->method('findOneBy')->willReturn(new User());
        $this->useCase->__invoke(new Request());
    }

    public function testGivenShortEmailThenThrowException()
    {
        $this->expectException(InvalidArgumentException::class);

        $this->useCase->__invoke(new Request(['username' => 'a']));
    }

    public function testGivenCorrectDataThenSaveUser()
    {
        $this->emailService->expects($this->once())->method('onUserCreated');
        $this->analyticsService->expects($this->once())->method('onUserCreated');

        $expectedUser = (new User())->setUsername('username')->setEmail('username@tips.com');

        $this->userRepository->expects($this->once())
            ->method('persist')
            ->with($this->equalTo($expectedUser));

        $returnedUser = $this->useCase->__invoke(new Request([
            'username' => 'username',
            'email' => 'username@tips.com'
        ]));

        $this->assertEquals($expectedUser, $returnedUser);
    }
}

Why?

There's plenty of literature about why you should test your app on the internet...you'll have less bugs, the ones you have you'll fix them faster, better app design...and you'll sleep better 😅

Thanks to our previous tips we only have to mock business services (and we will remove them in future tips), we can catch exceptions and test the result as an Object.

You can start doing TDD now!

What about the id?

We have a problem with that, the user id is being generated by the database (after the flush) and we can't test it right now 😱 let's solve it in the next tip.

You can run php ./vendor/bin/phpunit to run the tests.

Symfony tip completed 👍! Check the final code and leave a ⭐️!

Next Tip -> Symfony Tips #11 - Use Uuids as identifiers

Previous Tip -> Symfony Tips #09 - Catch exceptions in an Event Subscriber

HEY! Follow me at @albertobeiz if you found this tip useful or have any question.

Interested in reading more such articles from Alberto Beiz?

Support the author by donating an amount of your choice.

 
Share this