在 phpunit 中创建一个模拟而不模拟任何方法? [英] Creating a mock in phpunit without mocking any methods?

查看:16
本文介绍了在 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(),那么对象上的所有方法都会被mock,无法调用我想调用的方法测试;但是如果我 确实 调用 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天全站免登陆