在派生类中模拟数据库

时间:2014-08-26 07:13:14

标签: php testing mocking phpspec

我已经拥有实现特定接口的Repository类,并且还扩展了特定数据库的基类。

基类:

abstract class CouchDB
{
  protected $db;

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

  private function call_get($url) {...} //this is a wrapper for $db->get()
}

派生类:

class CouchExpression extends CouchDB implements ExpressionInterface
{
  public function __construct(Sag $db)
  {
    parent::__construct($db);
  }
}

规范:

class CouchExpressionSpec extends ObjectBehavior
{
  public function let($db)
  {
    $db->beADoubleOf('\Sag');

    $this->beConstructedWith($db);
  }

  public function it_gets_returned_by_its_id()
  {
     $this->db->get('...')->willReturn([]);
  }
}

运行PHPSpec时,我得到:property db not found 有没有办法解决这个问题,而不是将属性设置为public

将其设置为public后,我得到:call to a member function willReturn() on a non-object. 因此,我无法在->willReturn()

上运行$this->db

但为什么呢?在测试的let方法中执行此操作时,它可以正常工作。但并非所有测试都需要返回相同的数据......

如何让它运行?

1 个答案:

答案 0 :(得分:1)

您可以在没有显式调用的情况下声明您的double,如下所示:

function let(\Sag $db)
{
    $this->beConstructedWith($db);
}

完成此操作后,如果您将一个同名的属性传递给您的示例,它将是double的同一个实例:

function it_gets_returned_by_its_id($db)
{
    $db->get('...')->willReturn([]);
}

此外,根据惯例,让我们和示例方法不使用公共关键字,他们无论如何都会公开,并且它可以降低示例周围的噪音。