harryg
harryg

Reputation: 24077

Mock a public method of the class being tested

I'm trying to unit test a class where one public method (method 1) uses another public method (method 2) of the same class within it. E.g.

class MyClass {
    public function method1()
    {
        $var = $this->method2();
        // Do stuff with var to get $answer
        return $answer;
    }

    public function method2()
    {
        // Do complex workings out to get $var
        return $var;
    }
}

Now, method2 is already unit tested and I don't want to build up an argument for it to actually call it whilst testing method1. I just want to mock up method2 and define in my test what would be returned. This is what I have:

function test_method1()
{
    $myClass = new MyClass();

    $mockedMyClass = Mockery::mock('MyClass');
    $mockedMyClass->shouldReceive('method2')->once()->andReturn([1,2,3,4]); // mocked $var returned to be used in the rest of method1

    $answer = $myClass->method1();
    // Assertions
}

Clearly this doesn't work as the method being tested is in the same class as contains the method being mocked, so there's no way to pass in the mocked class as a dependency. What's the best way to mock just method2?

Upvotes: 1

Views: 136

Answers (1)

Matteo
Matteo

Reputation: 39400

You can use the Partial Mock functionality of the testing framework that permit you to test the same class you are marked as mocked. As example, suppose the your modified class:

<?php


namespace Acme\DemoBundle\Model;


class MyClass {
    public function method1()
    {
        $var = $this->method2();
        $answer = in_array(3, $var);
        // Do stuff with var to get $answer
        return $answer;
    }

    public function method2()
    {
        // Do complex workings out to get $var
        return array();
    }
}

And tested as follow:

<?php
namespace Acme\DemoBundle\Tests;


class MyClassTest  extends \PHPUnit_Framework_TestCase {

    function test_method1()
    {

        $mockedMyClass = \Mockery::mock('Acme\DemoBundle\Model\MyClass[method2]');
        $mockedMyClass->shouldReceive('method2')->once()->andReturn([1,2,3,4]); // mocked $var returned to be used in the rest of method1

        $answer = $mockedMyClass->method1();
        $this->assertTrue($answer);        // Assertions
    }

}

Hope this help

Upvotes: 2

Related Questions