Is interfaces need in PHP when using mocks in unit tests?

Hi,

I’ve just started working with unit testing in PHP and is thinking about using mocks. I’m wondering if it is needed to make all the classes implement an interface so that constructors can take parameters like

function __construct(IRequest $request)

and then make it possible to send in mocks.

Or can I just do

function __construct(Request $request)

and still send in mocks in the tests?

Not really helpful, but I do this for nearly all my objects now. Unit Testing aside, the benefits far outweigh the extra upfront dev time I find.

Could you list some of the benefits?

Also, do you create interfaces for all your classes?

Primarily, in a word, flexibility. Take the following ability to transform the User object without internal modification of it and other accepting objects.


$user = new User('anTHony', 'sterLIng');
$printer = new UserPrinter($user);
echo $printer->render(); #sterling, a. (anthony)


$user = new User('anTHny', 'sterLIng');
$printer = new UserPrinter(new UserUCWordsDecorator($user));
echo $printer->render(); #Sterling, A. (Anthony)


interface IRenderable
{
    public function render();
}

interface IUser
{
    public function getFirstname();
    
    public function getLastname();
}

class UserPrinter implements IRenderable
{
    protected
        $user;
       
    public function __construct(IUser $user){
        $this->user = $user;
    }
    
    public function render(){
        return sprintf(
            '%s, %s. (%s)',
            $this->user->getLastname(),
            substr($this->user->getFirstname(), 0, 1),
            $this->user->getFirstname()
        );
    }
}

class User implements IUser
{
    protected
        $firstname = null,
        $lastname = null;
    
    public function __construct($firstname, $lastname){
        $this->firstname = $firstname;
        $this->lastname = $lastname;
    }
    
    public function getFirstname(){
        return $this->firstname;
    }
    
    public function getLastname(){
        return $this->lastname;
    }
}

class UserUCWordsDecorator implements IUser
{
    protected
        $user;
    
    public function __construct(IUser $user){
        $this->user = $user;
    }
    
    public function getFirstname(){
        return ucwords(
            strtolower($this->user->getFirstname())
        );
    }
    
    public function getLastname(){
        return ucwords(
            strtolower($this->user->getLastname())
        );
    }
}

Basic yes, but now imagine printer object was your front controller and the user object needed to be presented in a myriad of different formats (json, xml, html, csv, text, vcard). You would just have to write a decorator and nothing else.

Thanks for describing it some more and sorry for missing the “for nearly all my objects” the first time :slight_smile: