是否可以使用普通的PHP或Mockery覆盖类的方法?

时间:2015-01-12 17:58:29

标签: php testing mockery

以下示例将最好地说明我的问题:

class a
{
    function a()
    {
         return file_get_contents('http://some/third/party/service');
    }
}

class b
{
    function b()
    {
        $a = new a();
        return $a->a() . ' Bar';
    }
}

class testB extends test
{
    function testB()
    {
        $b = new b();

        // Here we need to override a::a() method in some way to always return 'Foo'
        // so it doesn't depend on the third party service. We only need to check
        // the $b::b() method's behavior (that it appends ' Bar' to the string).
        // How do we do that?

        $this->assert_equals('Foo Bar', $b->b());
    }
}

让我指出,我无法控制定义/包含类'a'的位置。

2 个答案:

答案 0 :(得分:1)

你可以消除你的依赖:

首先,您创建一个界面,列出您需要的所有方法:

interface Doer {
    function a();
}

然后为您创建一个适配器类:

class ADoer implements Doer
{
   protected $dependencyA;

   public function __construct(A $dep) {
       $this->dependencyA = $dep;
   }

   public function a() {
       $this->dependencyA->a();
   }
}

现在让你的B类依赖于Doer接口,而不是A实现:

class B {
   private $doer;
   public function __construct(Doer $a) {
      $this->doer = $a;
   }

   public function b() {
      $this->doer->a();
   }

   public function setDoer(Doer $a) {
       $this->doer = $a;
   }

   //getDoer()
}

现在你可以随意切换它:

class FooDoer implements Doer {
   function a() {
      //do whatever you want
   }

}
$b->setDoer(new FooDoer());
$b->b();

答案 1 :(得分:1)

如果您更改了类b,以便可以传入a的实例:

class b
{
    function b($a = null)
    {
        if ($a == null) {
            $a = new a();
        }

        return $a->a() . ' Bar';
    }
}

...然后进行测试,您可以使用像Mockery这样的框架来传递一个模拟的' a'总是会回归Foo'

use \Mockery as m;

class testB extends test
{

    public function tearDown()
    {
        m::close();
    }

    public function testB()
    {
        $mockA = m::mock('a');
        $mockA->shouldReceive('a')->times(1)->andReturn('foo');

        $b = new b($mockA);

        $this->assert_equals('Foo Bar', $b->b());
    }

}

请在此处查看Mockery的完整文档和示例:http://docs.mockery.io/en/latest/getting_started/simple_example.html