Mike Funk
Mike Funk

Reputation: 363

PHPUnit - breaking code into testable chunks

I read somewhere that it's a good idea to break methods down into smaller, testable functions so that the smaller methods can be tested. But I'm confused on how to test the method that calls the smaller method. Here's an example:

class MyTestableClass
{
    public function myHugeFunction($list, array $list_filter_params)
    {
        // do a bunch of stuff, then...
        foreach($list as $item) {
            $this->subFunction($item);
        }
    }

    public function subFunction()
    {
        // do stuff for each item
    }
}

and the test class:

class MyTestableClassTest extends PHPUnit_Framework_TestCase
{
    public function testSubFunction
    {
        // This tests the smaller, bite-size method, which is good.
    }
    public function testMyHugeFunction
    {
        // this tests the parent function *and* the subFunction. I'm trying
        // to test *just* the parent function.
    }
}

I know how to test the subFunction, but since I can't stub a method in the same class, I don't know how to test the parent method only. I'd like to find a way of somehow stubbing the subFunction to just return true.

Do you use Events and stub the event class? That's the only way I can think of to stub another method called in the same class.

Upvotes: 1

Views: 227

Answers (1)

Cyprian
Cyprian

Reputation: 11374

Apart from things what @fab said in his comment (which you really should consider!), actually you can stub / mock methods in the SUT. For your example, build your SUT object may looks like:

class MyTestableClassTest extends PHPUnit_Framework_TestCase
{
    public function testSubFunction
    {
        // This tests the smaller, bite-size method, which is good.
    }
    public function testMyHugeFunction
    {
        // first, prepare your arugments $list and $list_filter_params
        // (...)

        // Next build mock. The second argument means that you will mock ONLY subFunction method
        $this->sut = $this->getMock('Namespace\MyTestableClass', array('subFunction'));

        // now you can set your subFunction expectations:
        $this->sut->expects($this->exactly(count($list))
            ->with($this->anything()); // of course you can make this mock better, I'm just showing a case

        // start testing
        $this->sut->myHugeFunction($list, $list_filter_params);
    }
}

PS And again, as @fab said: if you show a specific case, I'm sure you'll get a lot of good answers from people here.

Upvotes: 1

Related Questions