i was wondering on how i can mock a method on the same class that this class have a dependency itself.
Let's say an example:
Class SomeClassA {
protected $dependency;
function __construct(Dependency $dependency) {
$this->dependency = $dependency;
}
public function methodToTest() {
if ( !is_null( $this->methodCalled() ) )
return $this->methodCalled();
else
return "it\'s not ok!"
// need to test this method mocking the methodCalled()
}
public function methodCalled($message) {
return $message;
}
}
if this class did not have the dependency i could do something like so:
public function test_methodToTest() {
$this->getMock('SomeClassA',['methodCalled'])
->with('message')
->expects($this->once())
->will($this->returnValue('message'));
$someClassA = new SomeClassA();
$this->assertEquals('message',$someClassA->methodToTest('message'));
}
Edit:
Let's say this example to improve the meaning of my question i just changed a little bit the previous example:
Class SomeClassA {
protected $dependency;
function __construct(Dependency $dependency) {
$this->dependency = $dependency;
}
public function methodToTest() {
if ( $this->methodCalled() ) // i was wondering how mock this method
return $this->dependency->someDependencyMethod(); // not this
else
return "it\'s not ok!"
}
public function methodCalled() {
return true;
}
}
I just didn't understand how I can mock the method $this->methodClass()
. I found hard it because the class SomeClassA have a dependency. And i'm testing a method of that class.
You can do as follows:
class SomeClassATest {
public function testMethodToTest() {
$someClassA = $this->getMockBuilder('SomeClassA')
->setMethods(array('methodCalled'))
->getMock();
$someClassA->expects($this->once())
->method('methodCalled')
->will($this->returnValue('your mocked value here'));
$actual = $someClassA->methodToTest();
$this->assertEquals('your expectation here', $actual);
}
}
This will only work if methodCalled
is either public or protected, since you can only mock public and protected methods. The way it works up there is you are testing $someClassA
, a mock instance of SomeClassA
, where only methodCalled
is replaced with your test behavior, and everything else stays the same.
You'll be doing this a lot with unit tests:
To show a real example, your dependency needs to be actually used (which it isn't in your sample code, I think your code may be broken). So lets change your methodToTest
class to this as an example:
public function methodToTest() { return $dependency->returnValue(); }
So now your methodToTest
returns a value it gets from dependeency. To test this, lets mock a dependency:
$dep = $this->getMock('Dependency');
Then lets set expectations and what it returns:
$dep->expects($this->once())
->method('returnValue')
->will($this->returnArgument('hello world'));
Here we are saying that the dependency expects returnValue
to be called once and will return the string 'hello world'.
Now lets test the actual class:
$tester = new SomeClassA($dep);
Notice we inject the mock dependency into a real SomeClassA
.
$this->assertEquals('hello world',$tester->methodToTest());
This assertion is the only 'visible' one. It makes sure that methodToTest
returns the value from the dependency. The test will also make sure that 'returnValue' function on the dependency is called exactly once.