returncallback - phpunit with()




Creating a mock in phpunit without mocking any methods? (4)

When I'm unit-testing my php code with PHPUnit, I'm trying to figure out the right way to mock an object without mocking any of its methods.

The problem is that if I don't call getMockBuilder()->setMethods(), then all methods on the object will be mocked and I can't call the method I want to test; but if I do call setMethods(), then I need to tell it what method to mock but I don't want to mock any methods at all. But I need to create the mock so I can avoid calling the constructor in my test.

Here's a trivial example of a method I'd want to test:

class Foobar
{
    public function __construct()
    {
        // stuff happens here ...
    }

    public function myMethod($s)
    {
        // I want to test this
        return (strlen($s) > 3);
    }
}

I might test myMethod() with:

$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));

But this would call Foobar's constructor, which I don't want. So instead I'd try:

$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

But calling getMockBuilder() without using setMethods() will result in all of its methods being mocked and returning null, so my call to myMethod() will return null without touching the code I intend to test.

My workaround so far has been this:

$obj = $this->getMockBuilder('Foobar')->setMethods(array('none'))
    ->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

This will mock a method named 'none', which doesn't exist, but PHPUnit doesn't care. It will leave myMethod() unmocked so that I can call it, and it will also let me disable the constructor so that I don't call it. Perfect! Except that it seems like cheating to have to specify a method name that doesn't exist - 'none', or 'blargh', or 'xyzzy'.

What would be the right way to go about doing this?


Another hacky, but succinct solution is simply to list the magic constructor as one of the mocked methods:

$mock = $this->getMock('MyClass', array('__construct'));

Or you can just use getMock() directly.

$mock = $this->getMock('MyClass', null, array(), null, false);


How to test Doctrine Custom Types

Through a combination of not replacing any methods in a mock and some tips from an issue on github I was able to make a unit test for a doctrine type. I guess this works for simpler types where the platform isn't relevant. For more complex type behavior you could substitute the platform with a different mock.

/**
 * @test
 */
public function willCastValueToInt()
{
    $typeBuilder = $this
        ->getMockBuilder(IntegerType::class)
        ->disableOriginalConstructor()
        ->setMethods(null);

    $type = $typeBuilder->getMock();
    $platform = $this->getMockForAbstractClass(AbstractPlatform::class);

    $result = $type->convertToPHPValue('3', $platform);

    $this->assertSame(3, $result);
}

Replacing service in Symfony2 for testing dynamically

You can create an instance of ApiConnector using new keyword, inject mock Guzzle and use it for testing.

Another option you have is you can mock ApiConnector while mocking only some of it methods (maybe the ones doing the actual connections?) using phpUnit's setMethods.