johnlemon
johnlemon

Reputation: 21449

How to unit test a method with dependencies in PHP?

I have a method with some logic in it and I'm not sure how to unit test it. Because it's a unit test for this specific method it should run without connecting to the database. I read about stubs and mockups but I can't find a way to apply them to this situation.

I would like to force the Client:GetClient to return the client object with the right properties so I can test each logic branch.


class ClientType {
    function GetClientType($id) {

    $objClient = Client::GetClient($id);

    if ($objClient->Returning == 1) {
        return 'returning';
    }
    else {
        return 'normal';
    }
    }


This is the test I had in mind


class ResourceTest extends PHPUnit_Framework_TestCase {
    function testGetClientType() {
        $objClientType = new ClientType();
        $this->assertTrue($objClientType->GetClientType(100), 'normal');
    }
}

The problem is the dependency $objClient = Client::GetClient($id); The GetClient will pull a client from database but I need to replace this with a Stub so the unit tests work without real access to the database.

Conclusion

  • If you have code like the one presented: refactor it and use Dependency Injection.
  • If you have legacy code or just don't want to refactor try this solution: http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html

    Upvotes: 5

    Views: 4721

  • Answers (2)

    Gordon
    Gordon

    Reputation: 316969

    With PHPUnit you can do

      $class = $this->getMockClass(
          'Client',          /* name of class to mock     */
          array('getClient') /* list of methods to mock   */
        );
        $class::staticExpects($this->any())
              ->method('getClient')
              ->will($this->returnValue('foo'));
    

    In general, you want to avoid static methods though:


    EDIT after update

    PHPUnit can also stub hardcoded dependencies. See

    However, since you already noticed by now that it is a Pain the Behind to test statics and hardcoded dependencies, I suggest you remove the hardcoded dependency and static call with a real object that you inject into your ClientType instead.

    Another option would be to use http://antecedent.github.io/patchwork (not affiliated with it), which

    is a PHP library that makes it possible to redefine user-defined functions and methods at runtime, loosely replicating the functionality runkit_function_redefine in pure PHP 5.3 code, which, among other things, enables you to replace static and private methods with test doubles.

    Upvotes: 5

    Shankar Raju
    Shankar Raju

    Reputation: 4546

    Try Mocking for such kind of a problem. I do not know PHP, but we do mocking in Java and C# in such a scenario.

    EDIT

    I'm sorry I didn't see that you were facing a problem with mocks. Well usually for Mocks you tell them what you expect from them and they respond to the same. LSV principle is being used in mocks. As for PHP, I'm sorry I have no idea on what tool to use for mocks and how you use them

    Upvotes: 0

    Related Questions