dimanche 4 novembre 2018

How to create test doubles for functions which use database connection PHPUnit

I want to create CRUD application and learn how to unit test while doing it using PHPUnit. I have fetchAllTasks() and AddTask() function which i want to unit test.

I managed to make testFetchAllTasks() pass but i when i want to add expects($this->once()) i keep getting error: Expectation failed for method name is equal to "fetchAll" when invoked 1 time(s). Method was expected to be called 1 times, actually called 0 times.

And i dont know how to test AddTask() function without inserting data into database. Someone please help.

Here is my code:

Database.php

<?php
  class Database {

    private $host = 'localhost';
    private $user = 'root';
    private $pass = '123456';
    private $dbname = 'todolist';

    private $dbh;
    private $stmt;
    private $error;

    public function __construct(){
      // Set DSN
      $dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
      $options = array(
        PDO::ATTR_PERSISTENT => true,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
      );

        // Create PDO instance
      try {
        $this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
      } catch(PDOException $e){
        $this->error = $e->getMessage();
        echo $this->error;
      }
    }

    public function query($sql){
      $this->stmt = $this->dbh->prepare($sql);
    }

    public function bind($param, $value, $type = null){
      if(is_null($type)){
        switch(true){
          case is_int($value):
          $type = PDO::PARAM_INT;
          break;
          case is_bool($value):
          $type = PDO::PARAM_BOOL;
          break;
          case is_null($value):
          $type = PDO::PARAM_NULL;
          break;
          default:
          $type = PDO::PARAM_STR;
        }
      }

      $this->stmt->bindValue($param, $value, $type);
    }


    public function execute() {
      return $this->stmt->execute();
    }

    public function fetchAll(){
      $this->execute();
      return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
    }
   }

Task.php

<?php

  require_once 'Database.php';

  class Task {

    private $db;

  public function __construct() {
        $this->db = new Database;
  }

    public function fetchAllTasks() {
      $this->db->query('SELECT * FROM tasks');
      $results = $this->db->fetchAll();

      return $results;
    }


    public function addTask($data){
      $this->db->query('INSERT INTO tasks (task_desc) VALUES (:task_desc)');

      $this->db->bind(':task_desc', $data);

      if($this->db->execute()) {
        return true;
      } else {
        return false;
      }
    }
  }

TaskTest.php

<?php
require_once './src/Task.php';
require_once './src/Database.php';
use PHPUnit\Framework\TestCase;

  class TaskTest extends TestCase {

    public function testFetchAllTasks() {

      $table = array(
        array(
          'task_id' => '1',
          'task_desc' => 'Task One Test'
        ),
        array(
          'task_id' => '2',
          'task_desc' => 'Task Two Test'
        )
      );

      $database = $this->createMock('Database');

      $database->method('fetchAll')
          ->willReturn($table);

      $expectedResult = [
                          'task_id' => '1',
                          'task_desc' => 'Task One Test',
                        ];

      $task = new Task();
      $actualResult =  $task->fetchAllTasks();

      $this->assertEquals($expectedResult, $actualResult[0]);  

    }

   public function testAddTask() {
    // Test goes here..
   }
  }

Aucun commentaire:

Enregistrer un commentaire