0

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)

2
  • 2
    PHPUnit works for dependency injection. You need to inject the mocked Two class into One. Also you didn't use the parameters of getMockBuilder method correctly. Commented Feb 4, 2015 at 16:29
  • Wherer I use badly the getMockBuilder? How can I inject the second mocked class into the first one? I don't found any example or documentation or anything for it, can you drop a link or something please? Commented Feb 4, 2015 at 20:38

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Good point, thanks for it!.... but the main problem is, I can't modify the original One and Two class and can't use any 3rd party lib for testing.
0

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.

2 Comments

Thanks the help, it's working. In other case the injection also working && yeah, i really use the mockbuilder wrongly. Thanks again!
It would be better to refactor the class, so that you use Dependency Injection but if you can't change the classes ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.