在不模拟任何方法的情况下在phpunit中创建模拟? [英] Creating a mock in phpunit without mocking any methods?

查看:47
本文介绍了在不模拟任何方法的情况下在phpunit中创建模拟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用PHPUnit对我的php代码进行单元测试时,我试图找出正确的方法来模拟对象而不模拟其任何方法.

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.

问题是,如果我不调用getMockBuilder()->setMethods(),则对象上的所有方法都将被模拟,而我无法调用要测试的方法.但是,如果我 do 调用setMethods(),那么我需要告诉它要模拟哪种方法,但是我根本不想模拟任何方法.但是我需要创建模拟程序,以便避免在测试中调用构造函数.

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);
    }
}

我可以用以下方法测试myMethod():

I might test myMethod() with:

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

但是这将调用Foobar的构造函数,我不希望这样做.因此,我会尝试:

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'));

但是不使用setMethods()调用getMockBuilder()将导致其所有方法都被模拟并返回null,因此我对myMethod()的调用将返回null而无需触碰要测试的代码.

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'));

这将模拟一个名为"none"的方法,该方法不存在,但PHPUnit不在乎.它将使myMethod()处于未模拟状态,以便我可以调用它,并且还可以使我禁用构造函数,以便不调用它.完美的!除了似乎不得不指定一个不存在的方法名称-'none'或'blargh'或'xyzzy'似乎在作弊.

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?

推荐答案

您可以将null传递给setMethods()以避免模拟任何方法.传递一个空数组将模拟所有方法.后者是您所找到方法的默认值.

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.

这篇关于在不模拟任何方法的情况下在phpunit中创建模拟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆