6

I want to test this code block which has to call a static class.

class SomeModule {
    public function processFoo() 
    {
        $foo = FooFactory::getFoo();

        // ... Do something to $foo

        return $foo;
    }
}

I can't modify the static class. I can however change the code inside the module. How can I refactor this code to be unit testable?

2 Answers 2

4

Moving the static call to a separate method which is then mocked

Refactored code:

class SomeModule {
    public function processFoo() 
    {
        $foo = $this->getFoo();

        $foo['hoopla'] = 'doo';

        return $foo;
    }

    protected function getFoo() 
    {
        return FooFactory::getFoo();
    }
}

Test code:

function testSomeModule() {
    // Whatever we want to simulate FooFactory::getFoo returning
    $foo = array('woo' => 'yay')

    // Create a copy of the class which mocks the method getFoo
    $module = $this->getMockBuilder('SomeModule')
                   ->setMethods(array('getFoo'))
                   ->getMock();

    // Rig the mock method to return our prepared sample
    $module->expects($this->once())
           ->method('getFoo')
           ->will($this->returnValue($foo));

    $result = $module->processFoo();

    $this->assertEquals('yay', $result['woo']);
    $this->assertEquals('doo', $result['hoopla']);
}
Sign up to request clarification or add additional context in comments.

Comments

1

Passing the static class name as a constructor parameter

Refactored code:

class SomeModule {
    protected $factoryName;

    public function __construct($factoryName = 'FooFactory') {
        $this->factoryName = $factoryName;
    }

    public function processFoo() 
    {
        // PHP Parser limitation requires this
        $factoryName = $this->factoryName;
        $foo = $factoryName::getFoo();

        $foo['hoopla'] = 'doo';

        return $foo;
    }
}

Test code:

public class MockFactory {
    static public function getFoo() {
        return array('woo' => 'yay');
    }
}

function testSomeModule() {
    $module = new SomeModule('MockFactory');
    $result = $module->processFoo();

    $this->assertEquals('yay', $result['woo']);
    $this->assertEquals('doo', $result['hoopla']);
}

1 Comment

I made a library that allows to stub static classes, so you can do same without creating "MockFactory" class: github.com/shagabutdinov/moka

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.