Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
292 views
in Technique[技术] by (71.8m points)

Creating a mock in phpunit without mocking any methods?

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?

question from:https://stackoverflow.com/questions/9398284/creating-a-mock-in-phpunit-without-mocking-any-methods

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...