Danylo Mysak
Danylo Mysak

Reputation: 1512

Is it possible to override method of the class with plain PHP or Mockery?

My question would be best illustrated by the following example:

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());
    }
}

Let me point out that I don't have the control over where class 'a' is being defined/included.

Upvotes: 0

Views: 1283

Answers (2)

bhb603
bhb603

Reputation: 481

If you changed class b so that the instance of a can be passed in:

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

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

...then for test, you can use a framework like Mockery to pass in a mocked instance of 'a' which always returns '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());
    }

}

See the full docs and examples for Mockery here: http://docs.mockery.io/en/latest/getting_started/simple_example.html

Upvotes: 1

Waldson Patricio
Waldson Patricio

Reputation: 1529

You can eliminate your dependency like that:

First you create an interface that will list all methods you need:

interface Doer {
    function a();
}

Then create an adapter class for you a class:

class ADoer implements Doer
{
   protected $dependencyA;

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

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

Now make your B class depends on Doer interface, not on A implementation:

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()
}

Now you can switch it at will:

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

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

Upvotes: 1

Related Questions