php - 您可以在回调中使用 $this 来获取 phpunit 中模拟类的 protected 属性吗?

标签 php unit-testing mocking phpunit

你能在回调中使用 $this 来获取 phpunit 中模拟类的 protected 属性吗? 或者有其他方法可以实现吗?

 $mock = $this->getMock('A', array('foo'));
 $mock->expects($this->any())->method('foo')->will(
     $this->returnCallback(function() {
         return $this->bar;
 }));

如果您考虑注入(inject)模拟对象,这可能非常有用。 有时类对其他类具有硬编码依赖性,但它使用理论上可以模拟并创建模拟对象而不是硬编码对象的方法来创建它。请看另一个例子。

class A {
  protected $bar = "bar";

  public function foo () {
    $b = new B();
    return $b->fizz($this->bar);
  }
}

class B {
  public function fizz ($buzz) {
    return $buzz;
  }
}

但是假设类 B 做了一些坏事,我想用 mock 替换它。

 $mockB = $this->getMock('B');
 // (...) - and probably mock other things
 $mockA = $this->getMock('A', array('foo'));
 $mockA->expects($this->any())->method('foo')->will(
     $this->returnCallback(function() use ($mockB) {
         return $mockB->fizz($this->bar);
 }));

这是可以实现的吗?

当然没有任何意外,目前,如果我像上面那样做,我会得到错误:

PHP Fatal error:  Using $this when not in object context in (...)

使用 use 关键字我可以从父作用域继承 $mockA:

 $mockB = $this->getMock('B');
 // (...) - and probably mock other things
 $mockA = $this->getMock('A', array('foo'));
 $mockA->expects($this->any())->method('foo')->will(
     $this->returnCallback(function() use ($mockA, $mockB) {
         return $mockB->fizz($mockA->bar);
 }));

但是通过这种方式我将尝试以公共(public)方式访问 bar 并且我将得到:

PHP Fatal error:  Cannot access protected property (...)

最佳答案

正如其他答案所指出的,自 PHP 5.4 起,$this 可用于闭包。一个鲜为人知的事实是,您可以将闭包绑定(bind)到任意对象,实际上可以像那样访问它们的私有(private)属性。你需要的方法是bindTo() ,它返回一个具有不同上下文的新闭包

$cb = function() {
  return $this->bar;
};
$cb = $cb->bindTo($mockA);

或者更准确地说,你的例子看起来像这样:

 $mockB = $this->getMock('B');
 // (...) - and probably mock other things
 $mockA = $this->getMock('A', array('foo'));
 $fooCallback = function() use (&$mockB) {
     return $mockB->fizz($this->bar);
 };
 $mockA->expects($this->any())->method('foo')->will(
     $this->returnCallback($fooCallback->bindTo($mockA)));

关于php - 您可以在回调中使用 $this 来获取 phpunit 中模拟类的 protected 属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14792929/

相关文章:

php - 按照用户的样式将用户输入插入 mysql 数据库(带换行符)

c# - 类库(包).Net 4.6 的单元测试

Django 在运行测试时不创建测试数据库

unit-testing - junit测试应使用main/resources

database - Mock 框架可以为我做这个吗?

ruby - 摩卡和嵌套对象

embedded - 一组一致且简单的IDE和用于C++的嵌入式代码和单元测试的工具?

php - MYSQL 使用 AND 和 OR 从数据库中选择数据

php - 何时在 Laravel 中使用 Eloquent 模型

php - XML 命名空间如何工作?