【问题标题】:PHPUnit Mocking functions which use Database Connection使用数据库连接的 PHPUnit 模拟函数
【发布时间】:2019-04-06 18:52:40
【问题描述】:

我是使用 PHPUnit 的新手,我正在尝试测试需要从数据库中获取所有任务的函数 getAllTask​​s()。我尝试了一切,但我只是让我的代码变得更糟。所以请帮我解决这个问题。 TaskTest.php 是我试图进行测试但它不起作用的东西。当然,如果有更好的方法来做某事,我也喜欢学习新东西。这是我的代码:

编辑:我更改了 TaskTest.php 的代码,并设法通过了测试。有人可以告诉我这是测试此功能的好方法,还是有更好的方法?谢谢!

任务.php

<?php

  require_once 'Database.php';

  class Task {
    private $db;

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

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

      return $results;
    }
} 

数据库.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);
      $this->execute();
    }

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

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

    }
}

TaskTest.php

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

  class TaskTest extends TestCase {

    public function testGetAllTasks() {

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

      $dbase = $this->getMockBuilder('Database')
        ->getMock();

      $dbase->method('resultSet')
          ->will($this->returnValue($table));

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

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

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

    }
}

【问题讨论】:

  • 我很乐意提供帮助,尤其是在测试方面!但是……到底是什么问题……?
  • @Loek 问题是当我运行测试时它说:调用 1 次时方法名称的期望失败等于“查询”。方法预期调用1次,实际调用0次。

标签: php mocking phpunit


【解决方案1】:

您将模拟传递给 Task 类构造函数,但它没有做任何事情。

$task = new Task($resultSetMock);

更新了代码以便使用:

class Task {
    private $db;

    public function __construct( ?Database $db = null ) {
        // set the db if none is provided
        if( is_null($db) )
        {
            $db = new Database;
        }

        $this->db = $db;
    }

    // ...
}

【讨论】:

  • 我使用了你的代码,但是现在还有一个问题:Uncaught ArgumentCountError: Too little arguments to function Task::__construct(),
  • @iposave 正确,我忘记了初始值(= null)。 ? 声明变量可以是null 或来自Database 类型。更新了答案。
  • 我设法通过了测试,并更改了有问题的代码。是测试getAllTask​​s()函数的好方法吗?
  • @iposave 很高兴听到代码有效。请接受答案,因为这解决了您的主要问题。关于测试的另一个问题;如果您想检查getAllTasks() 是否正确处理数据库的结果,那么可以。如果你想检查数据库是否被触及,那么你可以使用-&gt;expects( $this-&gt;once() ) 来模拟并放弃相等的断言。继续阅读有关何时存根和何时模拟的单元测试。
  • 当我使用 expects($this->once()) 时会发生此错误:调用 1 次时,方法名称的预期失败等于“resultSet”。方法预期调用1次,实际调用0次。
猜你喜欢
  • 2015-10-03
  • 2013-02-23
  • 2011-03-14
  • 2017-01-13
  • 2011-10-24
  • 2020-05-08
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多