pr0ggy/

此包已被废弃,不再维护。没有建议替代包。

可模拟的单例行为特性

0.3 2016-07-16 23:58 UTC

This package is not auto-updated.

Last update: 2021-06-12 02:13:38 UTC


README

单例设计模式有其用途,但常常在客户端代码中被过度使用,使得单元测试变得困难。考虑一个临时的数据库查询示例

function executeQuery($query, $parameters)
{
	$connection = DBConnectionPool::getInstance()->getConnection();
	$statement_handle = $connection->executeQuery($query, $parameters)
	// ...

	return $result_rows;
}

我们如何验证上述示例函数从连接池中获取连接,并验证返回的连接对象上调用的是预期方法?使用纯内部实例化的传统单例模式,由于无法替换 DBConnectionPool 实例为测试替身,测试将变得非常麻烦。

此特性通过暴露一些新方法来解决这个问题,这些方法实现了单例目标:限制实例化为单个实例,同时允许用测试替身替换实例。考虑以下使用测试框架(如 Peridotpho)的 describe-it 语法的简单示例

describe('executeQuery($query, $parameters)', function () {
	$this->original_pool_instance = DBConnectionPool::getInstance();
	$this->connection_pool_double = createConnectionPoolTestDouble();

	function createConnectionPoolTestDouble()
	{
		// ...
	}

	beforeEach(function () {
		DBConnectionPool::unregisterSingletonInstance();
		DBConnectionPool::registerSingletonInstance(
			$this->connection_pool_double
		);
	});

	afterEach(function () {
		DBConnectionPool::unregisterSingletonInstance();
		DBConnectionPool::registerSingletonInstance(
			$this->original_pool_instance;
		);
	});

	it('should ask the DBConnectionPool singleton for a connection',
		function () {
			$this->connection_pool_double
				->shouldReceive('getConnection')
				->once();
	
			$some_query = 'SELECT * FROM SOME_TABLE';
			$some_parameters = [];
			executeQuery($some_query, $some_parameters);
		}
	);

	it('should...', function () {
		// ...
	});

	// ...
});

src/MockableSingletonBehavior.php 中查看完整接口