Self gloating in function mocker usage

The function mocker has been out for a day and it already made my life simpler.

The problem

In a world where WordPress comes with OOP APIs I’d use this

class My_Schedule() {

    protected $cron;
    protected $time;
    protected $interval;
    protected $events = array();

    public function set_cron(WP\Cron\Cron_Object $cron){
        $this->cron = $cron;
    }

    public function set_time($time){
        $this->time = $time;
    }

    public function set_interval($interval){
        $this->interval = $interval;
    }

    public function add_event($event){
        $this->events[] = $event;
    }

    public function set_events(array $events){
        $this->events = $events;
    }

    public function schedule_events(){
        foreach($this->events as $event){
            $this->cron->schedule_event($event, $this->time, $this->interval);
        }
    }

}

and I could test some cases like this

class My_Schedule_Tests extends \PHPUnit_Framework_TestCase {

    protected $mock_cron;
    protected $sut;

    public function setUp(){
        $this->mock_cron = $this->getMock('\WP\Cron\Cron_Object');
        $this->sut = new My_Schedule;

        $this->sut->set_time( 100 );
        $this->sut->set_interval( 500 );
        $this->sut->set_cron( $this->mock_cron );
    }

    public function test_schedule_events_wont_schedule_anything_if_no_events(){
        $this->mock_cron->expects($this->never())->method('schedule_event');

        $this->sut->schedule_events();
    }

    public function test_schedule_events_will_schedule_one_event(){
        $this->mock_cron->expects($this->once())->method('schedule_event')
            ->with('some', 100, 500 );
        $this->sut->set_events(array('some'));

        $this->sut->schedule_events();

    }
}

and that would be easy.

But it’s not like that

The class under test body would much likely be like this

class Real_Schedule() {

    protected $time;
    protected $interval;
    protected $events = array();

    public function set_time($time){
        $this->time = $time;
    }

    public function set_interval($interval){
        $this->interval = $interval;
    }

    public function add_event($event){
        $this->events[] = $event;
    }

    public function set_events(array $events){
        $this->events = $events;
    }

    public function schedule_events(){
        foreach($this->events as $event){
           wp_schedule_event($this->time, $this->interval, $event);
        }
    }

}

and have fun testing it without a WP Loader.
Here it comes function mocker.

Testing a function

While function mocker is far from being a mature and complete tool it allows right now tests like the ones above to be rewritten in a civil way

class Real_Schedule_Tests extends \PHPUnit_Framework_TestCase {

    protected $sut;

    public function setUp(){
        FunctionMocker::setUp();

        $this->sut = new My_Schedule;

        $this->sut->set_time( 100 );
        $this->sut->set_interval( 500 );
    }

    public function tearDown(){
        FunctionMocker::tearDown();
    }

    public function test_schedule_events_wont_schedule_anything_if_no_events(){
        $wp_schedule_event = FunctionMocker::replace('wp_schedule_event');

        $this->sut->schedule_events();

        $wp_schedule_event->wasNotCalled();
    }

    public function test_schedule_events_will_schedule_one_event(){
        $wp_schedule_event = FunctionMocker::replace('wp_schedule_event');
        $this->sut->set_events(array('some'));

        $this->sut->schedule_events();

        $wp_schedule_event->wasCalledWithOnce(array('some', 100, 500));
    }

And I like that.

I appreciate your input