我正在重新设计一个应用程序,我选择使用TDD来完成它。我是TDD的新手,还没有爱上这个过程。目前,我遇到了一个问题,我无法找到任何明确的帮助。我可能只是过分思考,但肯定会感谢一些帮助,理解我遇到的问题。
我正在研究的项目仍然存在于MongoDB中。我已经和Mongo一起工作了一段时间并且很喜欢它,但PHP驱动程序似乎不适合我对如何(和什么)用假/模拟进行测试的有限理解。
这是一个示例类(我没有检查它是否会运行):
class UserCollection {
protected $_mongo_client; //connection to persistence layer (MongoDB or mock)
public function __construct($mongo_client, $id = NULL) {
$this->_mongo_client = $mongo_client;
}
public function getUserInfo($mid) {
$collection = $this->_mongo_client->vertical->primaryMember;
$user = $collection->findOne(array('memberId' => intval($mid)), array('memberId'=> true, 'name'=>true,'stats' => true));
if($user['memberId']) {
$return['status'] = "Success";
$return['user'] = $user;
} else {
$return['status'] = "Failure";
$return['message'] = "User not found";
}
return $return;
}
}
据我了解,如果我要先创建这个测试代码,我需要为数据库创建一个假 - 我一直试图想出一个模拟注入到构造函数中。如何创建处理如下行的模拟:
$collection = $this->_mongo_client->vertical->primaryMember;
我希望我只是在思考这个问题,并且有一种简单或更好的方法可以做到这一点。无论如何,我会很感激任何链接,圣人建议,或者对我的想法进行直接修正。
答案 0 :(得分:2)
对于那些可能偶然发现这种情况的人,我找到了几个解决方案。在上面引用的案例中,我意识到将MongoCollection作为依赖项传递更为合适,而且这些很容易被模拟。
然而,当我使用Mockery作为我的模拟库时,有一些处理" Demeter链"的选项,就像我特别询问的那样:
$collection = $this->_mongo_client->vertical->primaryMember;
以下是文档的链接:
http://docs.mockery.io/en/latest/reference/demeter_chains.html
它基本上表明你理论上可以像这样模仿链:
$mock = \Mockery::mock('\MongoClient');
$mock->shouldReceive('vertical->primaryMember')->andReturn($mockMongoCollection);
你可以返回任何你想要的东西,而且看起来是一个非常可行的解决方案。
答案 1 :(得分:2)
另一个问题here也解决了这个问题。
Phactory为模拟MongoDB提供直接支持。 Here is a complete example中来自Phactory创作者的guide explaining how to mock MongoDB in PHP。
修改:以上链接现已停止,而且Phactory似乎已不再维护。有一个名为`php-mongomock'的新项目旨在解决这个问题:
use Helmich\MongoMock\MockCollection;
$collection = new MockCollection();
$collection->createIndex(['foo' => 1]);
$documentId = $collection->insertOne(['foo' => 'bar'])->insertedId();
$collection->updateOne(['_id' => $documentId], ['$set' => ['foo' => 'baz']]);