Search code examples
phpsimpletest

Passing arguments to SimpleTest unit tests


I have a class that I am writing tests for using SimpleTest. There are static functions in the class that need to be passed my SQL connection object, that resides in Variables.php. How do i do this?

<?
   require_once('../Variables.php');


   class TestOfMember extends UnitTestCase {

      function testGetMembersFromEmailAddress() {

         $this->assertTrue($Member::getMembersFromEmailAddress("[email protected]", $conn)==null);
         $this->assertTrue($Member::getMembersFromEmailAddress("[email protected]", $conn)!=null);
      }
    }

?>


class Member {
public static function getMembersFromEmailAddress($emailAddress, $conn) {

    $args = array();
    $args[] = $conn;

    try {
        $result = $conn->query("SELECT * FROM members WHERE Members_Email ='" . $emailAddress . "'");
        $members = $result->fetchAll(PDO::FETCH_CLASS, 'Member', $args);

        return $members;
    } catch (PDOException $e) {
        echo $e->getMessage();
    }
}

}


Solution

  • What you describe is a typical problem. The easiest way to solve it is to use so called mock objects. These objects behave like they are a real object, but in fact they are just a thin shell. Plus: you have full control over them in your test.

    There are different ways to use mock objects, SimpleTest even has it's own implementation. Or you could use a framework like mockery.

    In your case, you need a database connection object (DatabaseConnection) with a query() method. This returns you a result object (Result), which in turn has a fetchAll() method and returns probably an array.

    I first declare two interfaces, this allows SimpleTest to mock the methods. If you already have declared classes for them you can just use them in Mock::generate() to generate a mock class.

    interface DatabaseConnection
    {
        function query();
    }
    
    interface Result
    {
        function fetchAll();
    }
    
    //this call generates a class called 'MockDatabaseConnection'
    //with the same interface as 'DatabaseConnection'
    Mock::generate('DatabaseConnection');
    Mock::generate('Result');
    
    class TestOfMember extends UnitTestCase
    {
       //this method gets called before each test method, it sets up each test
       function setUp() {
           $mockResult = new MockResult();
           //here I just return a string, but you could return a Member object as well
           $mockResult->returns('fetchAll', array("Member 1", "Member 2", "Member 3"));
           $this->mockConn = new MockDatabaseConnection();
           $this->mockConn->returns('query', $mockResult);
       }
    
       function testGetMembersFromEmailAddress() {
           $conn = new MockDatabaseConnection();
    
           //here you could now check for the mocked values "Member 1", "Member 2" ...
           $this->assertTrue(Member::getMembersFromEmailAddress("[email protected]", $this->mockConn)==null);
           $this->assertTrue(Member::getMembersFromEmailAddress("[email protected]", $this->mockConn)!=null);
       }
    }