告诉 phpunit 调用 public 而不是 private

Posted

技术标签:

【中文标题】告诉 phpunit 调用 public 而不是 private【英文标题】:Tell phpunit to call public instead of private 【发布时间】:2016-01-30 16:58:10 【问题描述】:

我的问题是。我有一门我想测试的课程(myClass)。在 myClass 中,有一个函数调用了 myClass 中的私有函数。

我知道我无法测试私有函数。是否可以告诉 phpunit 调用另一个函数而不是私有函数?

示例

$this->testclass 现在是我要测试的类

$this->testclass = new \stdClass();
$this->testclass->mock = $this->getMockBuilder('myClass')->getMock();

在我的测试用例之外,我创建了一个假类。

$this->mockextended = new \stdClass();
$this->mockextended->mock = new MOCKEXTENDEDCLASSES();

$this->mockextended 我有一个公共功能。

我要测试的功能

public function TestMe()
$this->somePrivateFunctioniHate(); <==== this is the pain in my ass

还有私有函数

private function somePrivateFunctioniHate()
   //come code
    

我想做的是。函数 TestMe 正在调用一个私有函数。 是否可以告诉 phpunit 覆盖私有函数并调用 $this-&gt;mockextended; 中的另一个函数 我试过这样。

$this->testclass->somePrivateFunctioniHate() = $this->mockextended->theWholeNewPrivateFunction()

只有这给了我一个很好的错误。我以前这样做过,它奏效了。这么称呼它

编辑 对于不理解我的问题的人。 我有另一个调用另一个类的函数。我不想在我的测试中有另一个类,所以我在我的测试用例之外创建了一个假类。插入了与函数想要包含的类相同的函数。是这样的吗

  $this->testclass->chunks = new \stdClass();
    //MOCKchunckTpl is the fake class outside my testcase
            $this->testclass->chunks->config = new MOCKchunkTpl(); 

这行得通。每当一个函数想要调用$this-&gt;testclass-&gt;chunks-&gt;config-&gt;Somefunction(); 时,它都会被重定向到我的假类。

但是 当我尝试对调用私有函数的函数执行相同操作时。就像$this-&gt;testclass-&gt;somePrivateFunctioniHate() = $this-&gt;mockextended-&gt;theWholeNewPrivateFunction() 一样,它给出了一个很好的错误

Fatal error: Can't use method return value in write context in

【问题讨论】:

为什么你总是先实例化一个new \stdClass(),然后再用你的模拟填充同一个变量? 我希望它像 $object->otherobject->anotherobject->thisonetoo 一样使用它...... 但是您正在立即覆盖该变量。在这两种情况下,stdClass 会丢失并且实例化毫无意义。 好吧。也许会的。但这不是我问的问题 这就是我在 cmets 中提到这一点的原因 【参考方案1】:

简短回答:不,没有。 PHPUnit 无法操作私有方法。

Mocks 用于伪造类的行为,这取决于您要测试的类。如果您需要覆盖私有方法,则说明您的架构中有问题。私有方法应该通过简单测试使用它们的公共方法来测试。如果需要单独测试,请声明为 public。

编辑:这是一个示例,您将如何使用私有方法或将此私有方法放在另一个类中测试简单代码:

1.私有方法

class MyClass 

    public function myMethod() 
        return $this->myPrivateMethod();
    

    private function myPrivateMethod() 
        return 2;
    


还有测试类:

class MyClassTest extends \PHPUnit_Framework_TestCase 

    public function testMyMethod() 
        $myClass = new MyClass();
        // don't mind the private method, just test if the public method is working
        $this->assertEquals(2, $myClass->myMethod());
    


1.二等

class MyClass 

    public $dependentClass;

    public function myMethod() 
        return $this->dependentClass->dependentMethod();
    


以及依赖类:

class DependentClass 

    public function dependentMethod() 
        return 38943;
    


使用DependentClass 测试MyClass

class MyClassTest extends \PHPUnit_Framework_TestCase 

    public function testMyMethod() 
        $dependentMock = $this->getMockBuilder("DependentClass")->getMock();
        $dependentMock->expects($this->any())
            ->method("dependentMethod")
            ->willReturn($this->returnValue(2));

        $myClass = new MyClass();
        $myClass->dependentClass = $dependentMock;

        $this->assertEquals(2, $myClass->myMethod());
    

尽管我们在 DependentClass 中定义了一个完全不同的返回值,但测试仍然会通过,因为我们模拟了它并且能够定义我们期望 DependentClass 具有的所有行为。

但是为了干净地测试项目,我们还需要为DependentClass 定义另一个测试来测试这个类是否正常工作。如果此测试不再有效,则该测试应该失败,而不是 MyClass 的测试。

【讨论】:

好吧。为什么它与我在问题中给出的最后一个例子一起工作? $this->testclass->mock->config = new someClass(); // 在这种情况下,您没有使用要测试的类的私有方法,而是使您的类依赖于另一个类。这是模拟对象的经典用例。所以通常你不会创建一个假类,而是获取你注入的类的模拟对象并调用它的方法。

以上是关于告诉 phpunit 调用 public 而不是 private的主要内容,如果未能解决你的问题,请参考以下文章

PHPUnit 测试使用 XAMPP localhost 而不是 laravel artisan serve

Laravel 路由仅在 phpunit 测试期间返回 302 而不是 404 响应

用 phpunit 模拟 symfony 安全,返回空值而不是布尔值(不使用预言)

在 Laravel 5.3 项目中使用 PHPUnit 存根类方法调用的问题

Laravel phpunit 没有得到正确的网址

PHPUnit 测试实际上运行代码而不是仅仅测试