0

This is my Database class and I want to test rowCount method returning correct value:

namespace MyProject\Database;

class Database {

    // database connection
    private $conn = NULL;

    // holds query statement object
    private $statement = NULL;

    public function __construct(\PDO $conn) {

        $this->conn = $conn;
    }

    public function query(string $query, array $parameters=[]) : bool {

        $this->statement = $this->conn->prepare($query);
        return $this->statement->execute($parameters);
    }

    public function rowCount() : int {

        return $this->statement->rowCount();
    }
}

I wrote this unit test at first to test rowCount method but as you can see I also used the query method to run the query:

class DatabaseTest extends \PHPUnit\Framework\TestCase {

    /** @test */
    public function rowCountReturnsCorrectNumber() {

        $pdo = new \PDO('sqlite::memory:');

        $db = new \MyProject\Database\Database($pdo);

        // we are not testing query method here but we use it to run the query
        $db->query("CREATE TABLE test (id INT UNSIGNED PRIMARY KEY)");
        $db->query("INSERT INTO test (id) VALUES (1),(2)");

        $this->assertEquals(2,$db->rowCount());
    }
}

I thought query method can have errors at the future so why should I depend on that. I wrote this to avoid it:

class DatabaseTest extends \PHPUnit\Framework\TestCase {

    /** @test */
    public function rowCountReturnsCorrectNumber() {

        $pdo = new \PDO('sqlite::memory:');

        $db = new \MyProject\Database\Database($pdo);

        $s = $pdo->prepare("CREATE TABLE test (id INT UNSIGNED PRIMARY KEY)");
        $s->execute();
        $s2 = $pdo->prepare("INSERT INTO test (id) VALUES (1),(2)");
        $s2->execute();

        // here I set statement (private property)
        $reflection = new \ReflectionClass($db);
        $property = $reflection->getProperty('statement');
        $property->setAccessible(true);
        $property->setValue($db, $s2);

        $this->assertEquals(2,$db->rowCount());
    }
}

Now my question is that: I think this is not a good approach while statement is a private property. On the 2nd test I can only test rowCount method and nothing else but I used private property and I think it can make maintenance so hard in the future. Which one is correct? Should I test it in another way?

0

1 Answer 1

1

You may use @depends which allows you to explicitly declare dependencies between your tests:

class DatabaseTest extends \PHPUnit\Framework\TestCase
{
  /**
   * @test
   */
  public function yourQueryTest()
  {
    // ...
  }


  /**
   * @test
   * @depends yourQueryTest
   */
  public function rowCountReturnsCorrectNumber()
  {
    // ...
  }
}

where yourQueryTest is a test for \MyProject\Database\Database#query.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.