Reputation: 658
I have two class, i want to test it via PHPUnit. But something i do wrongly at mocking the stuffs. I want to altering a method what called by the first class.
class One {
private $someVar = null;
private $abc = null;
public function Start() {
if ( null == $this->someVar) {
$abc = (bool)$this->Helper();
}
return $abc;
}
public function Helper() {
return new Two();
}
}
Class Two {
public function Check($whateverwhynot) {
return 1;
}
}
Class testOne extends PHPUnit_Framework_TestCase {
public function testStart() {
$mockedService = $this
->getMockBuilder(
'Two',
array('Check')
)
->getMock();
$mockedService
->expects($this->once())
->method('Check')
->with('13')
->will($this->returnValue(true));
$mock = $this
->getMockBuilder(
'One',
array('Helper'))
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('Helper')
->will($this->returnValue($mockedService));
$result = $mock->Start();
$this->assertFalse($result);
}
}
And the result is for the $result
is NULL
, instead of 'true
'
If I don't use the assert line, i get an error message:
F
Time: 0 seconds, Memory: 13.00Mb
There was 1 failure:
1) testOne::testStart
Expectation failed for method name is equal to <string:Check> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
Ideas?
Update - Environment: PHP 5.4.3x, PHPUnit 3.7.19 - An important thing: can't modify the original classes (Class One and Class Two)
Upvotes: 0
Views: 739
Reputation: 43700
You are creating your mocks wrong. You are using $this->getMockBuilder()
which takes only one argument, the name of the class to be mocked. You seem to be conflating it with $this->getMock()
that takes multiple.
Change the test to:
public function testStart() {
$mockedService = $this
->getMockBuilder('Two')
->setMethods(array('Check'))
->getMock();
$mockedService
->expects($this->once())
->method('Check')
->with('13')
->will($this->returnValue(true));
$mock = $this
->getMockBuilder('One')
->setMethods(array('Helper'))
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('Helper')
->will($this->returnValue($mockedService));
$result = $mock->Start();
$this->assertFalse($result);
}
This isn't a good test because we are needing mock the class that we are testing but you stated that you can't change the classes at all.
Upvotes: 0
Reputation: 6204
You can use mocks from ouzo-goodies.
Classes:
class One
{
private $someVar = null;
private $abc = null;
private $two;
public function __construct(Two $two)
{
$this->two = $two;
}
public function Start()
{
if (null == $this->someVar) {
$abc = (bool)$this->Helper()->Check(1213);
}
return $abc;
}
public function Helper()
{
return $this->two;
}
}
In constructor inject object Two
, thus you can easily mock this object.
class Two
{
public function Check($whateverwhynot)
{
return 1;
}
}
And tests:
class OneTest extends PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function shouldCheckStart()
{
//given
$mock = Mock::create('\Two');
Mock::when($mock)->Check(Mock::any())->thenReturn(true);
$one = new One($mock);
//when
$start = $one->Start();
//then
$this->assertTrue($start);
}
}
Docs for mocks.
Upvotes: 2