Php – Unit Testing and 3rd party packages. Do I mock or not

PHPtddtestingunit testing

I'm just getting used to unit testing and on my new project I decided to adopt a TDD approach.

My code below is to test the UserServices class which is responsible for creating a user, deleting a user, checking if a user exists etc.

Am I on the right lines? I ask because everywhere I look it discusses mocking and I can't help but think I should be mocking predis (a package used for interacting with Redis in PHP). But, mocking it would be difficult as my class expects an instance of Predis.

In the setup I create a dummy user to perform actions on. I may need to create more than one, but at this stage I just use the one. Although, there are methods such as createUser that would need to create an entirely new user.

<?php

namespace VoteMySnap\Tests;

class UserServicesTest extends \PHPUnit_Framework_TestCase
{
    const HOST = '127.0.0.1';
    const PORT = 6379
    const AUTH = NULL;

    public $predis;

    public function setUp()
    {
        $this->predis = new \PredisClient([
            'host' => HOST,
            'port' => PORT
        ]);

        /*
         * Create a dummy user
         */
        $dummyUser = [
            'user:1' => [
                'snapchat_username' => 'james16',
                'password' => 'somesecret',
                'email' => 'test@example.com'
            ]
        ];

       /*
        * Insert user into Redis
        */ 
        $this->predis->hmSet(key($dummyUser), $dummyUser[key($dummyUser)]);
    }

    public function tearDown()
    {
        /*
         * Remove the dummy user
         */
        $this->predis->delete(key($dummyUser));
    }  
}

Am I on the right tracks here?

Best Answer

I have always followed the maxim that a unit test tests one thing and only one thing. Programming such that each method does one thing and one thing only, should mean you can write a unit test for that method fairly easily.

If your method calls out to any other services or classes, then you should mock those so their behavior during the test is completely known. PHPUnit allows you to mock classes including those in packages you are using, eg PredisClient. You would want to also mock the hmSet method. I would recommend reading the following to gain a better understanding of how PHPUnit does this.

https://phpunit.de/manual/current/en/test-doubles.html

You may also want to refactor your code to instantiate PredisClient outside of the class you are testing (if you don't already) and then inject it via constructor parameter as this allows your mocked version to be easily injected. Search for Dependency Injection to see how this can help!

Related Topic