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 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误