【问题标题】:Test actual class method using mock object in PHPUnit在 PHPUnit 中使用 mock 对象测试实际的类方法
【发布时间】:2016-09-27 13:36:29
【问题描述】:

我想要做的:创建一个不执行 __constructor() 的 Mock 对象,但 DOES 具有所有已编码的方法(未模拟返回 null)。

The docs说:

"默认情况下,原类的所有方法都替换为 只返回 null 的虚拟实现(不调用 原始方法)。使用will($this->returnValue()) 方法,对于 例如,您可以配置这些虚拟实现以返回 调用时的值。”

这不是我想要的。我不想强制方法返回已知值。我想测试方法本身,因此需要类的功能实例化,但使用禁用的构造函数。

我该怎么做?

【问题讨论】:

  • 这真的引出了一个问题:你为什么不想执行构造函数?通常,这只是您绝对必须按书面执行的功能,以便正确设置对象来测试类。模拟对象用于该类的依赖关系,以便能够在不涉及第三方系统或其他业务代码的情况下对其进行正确测试。

标签: php unit-testing phpunit


【解决方案1】:

我为类本身编写了测试用例,以在给定所需参数的情况下返回数据,而不使用 Mocks。 Mocks 用于对此类的外部引用,需要知道函数 Bar() 返回 Foo,因此等待该响应的类会正确处理结果。

鉴于这个非常简单的 PHP 类:

<?php
class CATEGORY_SCOPE
{
    public $CategoryName;
    public $CategoryNo;

    function __construct($CategoryNo = NULL, $CategoryName = NULL)
    {
        $this->CategoryName = $CategoryName;
        $this->CategoryNo   = $CategoryNo;
    }

    protected function SetCategoryName($Name)
    {
        $this->CategoryName = Name;
    }
}
?>

然后我会测试它:

<?php
require_once(substr(__FILE__, 0, -5));  // strip '.test' extension
class TEST_CATEGORY_SCOPE extends PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
    }

    public function testObjectCreation()
    {
        $CategoryInfo = new CATEGORY_SCOPE();
        $this->assertInstanceOf('CATEGORY_SCOPE', $CategoryInfo);
    }

    public function testConstructFieldOrder()
    {
        $CategoryInfo = new CATEGORY_SCOPE(1500, 'Category Name');
        $this->assertEquals(1500, $CategoryInfo->CategoryNo);
        $this->assertEquals('Category Name', $CategoryInfo->CategoryName);
    }

    public function testConstructDefaults()
    {
        $CategoryInfo = new CATEGORY_SCOPE();
        $this->assertNull($CategoryInfo->CategoryNo);
        $this->assertNull($CategoryInfo->CategoryName);
    }

    public function testSetCategoryName()
    {
        $CategoryInfo = new CATEGORY_SCOPE();
        $CategoryInfo->SetCategoryName('New Name');
        $this->assertEquals('New Name', $CategoryInfo->CategoryName);
    }
}
?>

这将测试该类本身是否有效,并且我可以设置某些值。显然这是一个简单的例子。现在,当某些东西使用这个类时,我仍然可以对字段设置进行目录测试,但这在此处进行了介绍。

那么,对于您的问题,假设我有类 FOO() 接受 CATEGORY_SCOPE 作为构造函数中的参数。您将模拟 CATEGORY_SCOPE 类,并设置内部 Bar() 函数以返回一些数据,而不管 CATEGORY_SCOPE 类进行的处理。

<?php
class FOO
{
    public $ReturnValue
    function __construct($CategoryScope)
    {
        $this->ReturnValue = $CategoryScope->Bar();
    }
}
?>

通过模拟 CATEGORY_SCOPE 类,使 Bar() 函数始终返回 5(对您的代码有意义的某个值),然后您可以测试 FOO 类是否按预期工作。

<?php
require_once(substr(__FILE__, 0, -5));  // strip '.test' extension
class TEST_FOO extends PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
    }

    public function testObjectCreation()
    {
        $FooInfo = new FOO();
        $this->assertInstanceOf('FOO', $FooInfo);
    }

    public function testFoo()
    {
        // Set Up the Mock so Bar() returns 5 using your mock library

        ... <- Actual code for the mock goes here

        $FooInfo = new FOO($CategoryMock);
        $this->assertEquals(5, $FooInfo->Bar());
    }
}
?>

【讨论】:

    猜你喜欢
    • 2014-02-08
    • 2017-10-14
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 2016-01-05
    • 2014-07-06
    相关资源
    最近更新 更多