douxunchen3498 2017-06-17 13:15
浏览 57
已采纳

在PHPUnit中模拟紧密耦合的对象

For practice i'm creating my own database wrapper and query builder. When creating a DatabaseConnection object, a new PDO object is created in this object.

I have a Database class which depends on the DatabaseConnection object. This class builds the queries and executes them.

My DatabaseConnection class looks like this:

use PDO;

class DatabaseConnection
{
    /**
     * @var PDO $pdo The PDO connection object
     */
    private $pdo;

    public function __construct(array $credentials)
    {
        # Logic with $credentials to check on data
        $dsn = ...;
        # Open the connection
        $this->pdo = new \PDO($dsn, $credentials['username'], $credentials['password'], $options);
    }

    /**
     * Checks whether the connection is open or closed
     *
     * @return bool Whether the connection is open or closed
     */
    public function isConnected() : bool
    {
        return $this->pdo !== null;
    }

    /**
     * Retrieves the PDO connection object
     *
     * @return PDO The PDO connection object
     */
    public function getPDO() : PDO
    {
        return $this->pdo;
    }

    /**
     * Closes the connection
     */
    public function __destruct()
    {
        $this->pdo = null;
    }
}

When testing this, I ran across the problem that I always have to have a indentical database with the same login credentials on every computer i test this on.

For my research, I found out that I can create a mock objects, by doing

$pdo = $this->getMockBuilder('PDO')
    ->disableOriginalConstructor()
    ->getMock();

The problem here is that I can't inject the $pdo object into my DatabaseConnection class.

What am I doing wrong and how can I test this class without using an actual database by mocking data?

  • 写回答

1条回答 默认 最新

  • doutou6803 2017-06-17 13:25
    关注

    For your mock, create a subtype of the DatabaseConnection, override the constructor and make the PDO object injectable. Then you can mock the PDO object and create the full mock for mocking operations.

    Having "news" inside a constructor is a smell btw., your constructor should not do real work.

    As you have found out while testing, this makes your type hard to test. Creating a mock on your own (by writing it out) can lighten up the darkened sky.

    You might also not want to initialize the resources early, but connect to the database as late as possible. This would also move the new out of the constructor.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
  • ¥30 求解达问题(有红包)
  • ¥15 请解包一个pak文件