Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 称之为self-PhpUnit/mockry的Mock方法_Unit Testing_Phpunit_Mockery - Fatal编程技术网

Unit testing 称之为self-PhpUnit/mockry的Mock方法

Unit testing 称之为self-PhpUnit/mockry的Mock方法,unit-testing,phpunit,mockery,Unit Testing,Phpunit,Mockery,大家好,我有一个方法,给定一个确定的情况,它称之为自我,该方法的一个简短示例可以是: class MyClass { protected $quantity; public function add($quantity) { for($i = 0; $i < $quantity; $i++) { $newQuantity = $quantity - 1; $this->setQuantit

大家好,我有一个方法,给定一个确定的情况,它称之为自我,该方法的一个简短示例可以是:

class MyClass
{

   protected $quantity;

   public function add($quantity)
   {
       for($i = 0; $i < $quantity; $i++)
       {
           $newQuantity = $quantity - 1;

           $this->setQuantity($newQuantity);

           $this->add($this->quantity);
       }

       return $this->quantity;
   }

   public function setQuantity($quantity)
   {
        $this->quantity = $quantity;
   }
}
class-MyClass
{
受保护的数量;
公共功能添加(数量)
{
对于($i=0;$i<$quantity;$i++)
{
$newQuantity=$quantity-1;
$this->setQuantity($newQuantity);
$this->add($this->quantity);
}
返回$this->quantity;
}
公共函数设置数量($quantity)
{
$this->quantity=$quantity;
}
}
如果我想为这个丑陋的方法编写一个测试(只是为了举例),我会这样做:

<?php

use Mockery as m;

class TestMyClass
{

    public function teardown()
    {
       m::close();
    }

    public function test_add_method()
    {
        // Here come the problem because I need to mock that the method
        // will be called, but if I mock it, I cannot call it for an
        // assertion
        $mockMyClass = m::mock('MyClass[setQuantity,add]');

        $mockClass->shouldReceive('setQuantity')
                  ->once()
                  ->with(1)
                  ->andReturn(null);

        $result = $mockMyClass->add(1); // Here the problem

        $this->assertEquals(0,$result);
    }
}

嗯……你不需要那样做

您的类应该具有
getQuantity()
。只需运行
add()
,然后对
getQuantity()
执行断言

无论如何,您可以模拟
setQuantity()
(例如)来抛出异常。 然后断言
add
将引发异常


也许您可以使用
add(2)
,mock
add
测试特定参数:)

Hmm……您不需要这样做

您的类应该具有
getQuantity()
。只需运行
add()
,然后对
getQuantity()
执行断言

无论如何,您可以模拟
setQuantity()
(例如)来抛出异常。 然后断言
add
将引发异常


也许您可以使用
add(2)
,mock
add
测试,仅针对特定参数:)

基本经验法则:您不模拟要测试的类,句号

在某些情况下,此规则似乎不适用,但所有这些情况都表明您的类做了太多的事情,需要将其拆分为多个部分,然后可以模拟所有未测试的部分

现在,您似乎试图模拟一些东西,因为您想要测试内部递归调用。不要。因为它与外界无关,结果是如何实现的,无论是递归的还是迭代的。您始终可以将递归代码转换为交互代码,反之亦然,唯一的区别是,一种方法通常更适合问题

所以本质上你想做这样的事情:

public function test_add_one()
{
    $myClass = new MyClass();

    $result = $myClass->add(1); 

    $this->assertEquals(0,$result);
}

public function test_add_two()
{
    $myClass = new MyClass();

    $result = $myClass->add(2); 

    $this->assertEquals(0,$result); // I totally made this one up, haven't checked the code in detail
}

如果测试函数看起来是这样的,那么测试传递给add方法的任何参数的返回值始终为零都没有好处,这可能与您的示例代码没有显示任何其他可以观察到由代码执行触发的值更改的位置有关。

基本经验法则:不要模拟要测试的类,句号

在某些情况下,此规则似乎不适用,但所有这些情况都表明您的类做了太多的事情,需要将其拆分为多个部分,然后可以模拟所有未测试的部分

现在,您似乎试图模拟一些东西,因为您想要测试内部递归调用。不要。因为它与外界无关,结果是如何实现的,无论是递归的还是迭代的。您始终可以将递归代码转换为交互代码,反之亦然,唯一的区别是,一种方法通常更适合问题

所以本质上你想做这样的事情:

public function test_add_one()
{
    $myClass = new MyClass();

    $result = $myClass->add(1); 

    $this->assertEquals(0,$result);
}

public function test_add_two()
{
    $myClass = new MyClass();

    $result = $myClass->add(2); 

    $this->assertEquals(0,$result); // I totally made this one up, haven't checked the code in detail
}
如果测试函数看起来像这样,并且您没有看到任何好处,即无论您传递给add方法的参数是什么,返回值总是零,这可能与您的示例代码没有显示可以观察到由代码执行触发的值更改的任何其他位置有关