1

嗨,伙计们,我有一种方法可以在确定的情况下将其称为 self,该方法的一个简短示例可以是:

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

如果我想为这种丑陋的方法编写一个测试(仅出于示例目的),我会这样做:

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

但是我如何在代码上方编写注释,我无法正确地模拟该方法add,因为我需要对其进行断言,但即使是真的会再次调用并且我应该完成它的行为。

运行此单元测试的错误跟踪:

此模拟对象上不存在方法 Mockery_1_Mocks_My_Class::add()

你如何实现这个小功能的测试?

4

2 回答 2

3

基本的经验法则:你不要嘲笑你要测试的课程,期间。

在某些情况下,这条规则似乎不适用,但所有这些情况都表明你的班级做的事情太多,需要分成几部分,而你没有测试的所有部分都可以被嘲笑。

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

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

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 方法的任何参数,返回值始终为零,这可能与您的示例代码没有显示任何其他地方触发值更改可以观察到代码执行情况。

于 2014-07-07T22:22:48.743 回答
1

嗯....你不需要这样做。

你的班级应该有getQuantity(). 只需运行add(),然后执行 assert for getQuantity()

无论如何......你可以模拟setQuantity()(例如)抛出异常。然后断言add将抛出异常。

也许您可以使用, 仅针对特定参数进行add(2)模拟add:)

于 2014-07-03T12:26:06.207 回答