Creating a mock in phpunit without mocking any methods?

匿名 (未验证) 提交于 2019-12-03 01:49:02

问题:

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?

回答1:

You can pass null to setMethods() to avoid mocking any methods. Passing an empty array will mock all methods. The latter is the default value for the methods as you've found.

That being said, I would say the need to do this might point out a flaw in the design of this class. Should this method be made static or moved to another class? If the method doesn't require a completely-constructed instance, it's a sign to me that it might be a utility method that could be made static.



回答2:

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

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


回答3:

Or you can just use getMock() directly.

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



回答4:

This worked for me:

$this->getMock($class, array(), array(), '', false);


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!