, вот так:

у смоделировать метод класса и выполнить обратный вызов, который изменяет объект, заданный в качестве параметра (используя PHP 5.3 с PHPUnit 3.5.5).

Допустим, у меня есть следующий класс:

class A
{
  function foobar($object) 
  {
    doSomething();
  }
}

И этот код настройки:

$mock = $this->getMockBuilder('A')->getMock();
$mock->expects($this->any())->method('foobar')->will(
  $this->returnCallback(function($object) {
    $object->property = something;
  }));

По какой-то причине объект не изменяется. Наvar_dumpИНГ$object Я вижу, что это правильный объект. Может ли быть так, что объект передается по значению? Как я могу настроить макет для получения ссылки?

Ответы на вопрос(1)

Решение Вопроса

я говорил с Себастьяном (создателем phpunit) об этой проблеме и да: аргументcloneперед передачей в обратный вызов.

От всей души я не могу предложить вам никакого обходного пути, но я все равно хочу ответить, чтобы хотя бы сказать вам, что вы не делаете ничего плохого и что это ожидаемое поведение.

Цитируя Себастьяна, прокомментируйте IRC, почему он клонирует аргумент

Это давняя дискуссия между мной, мной и пользователями PHPUnit, правильно ли это или нет ;-)

Чтобы иметь что-то копируемое / вставляемое:

Утверждение 3 в этом примере кода потерпит неудачу. (Переменная изменяется только в возвращаемом объекте)

<?php
class A
{
    function foobar($o)
    {
        $o->x = mt_rand(5, 100);
    }
}

class Test extends PHPUnit_Framework_TestCase
{
    public function testFoo()
    {
        $mock = $this->getMock('A');
        $mock->expects($this->any())
             ->method('foobar')
             ->will($this->returnCallback(function($o) { $o->x = 2; return $o; }));

        $o = new StdClass;
        $o->x = 1;

        $this->assertEquals(1, $o->x);
        $return = $mock->foobar($o);

        $this->assertEquals(2, $return->x);
        $this->assertEquals(2, $o->x);
    }
}

Обновить:

Начиная с PHPUnit 3.7, клонирование можно отключить. См последний аргумент выключен:

public function getMock(
    $originalClassName, 
    $methods = array(), 
    array $arguments = array(), 
    $mockClassName = '', 
    $callOriginalConstructor = TRUE, 
    $callOriginalClone = TRUE, 
    $callAutoload = TRUE, 
    $cloneArguments = FALSE
);

Это может даже быть выключено по умолчанию :)

 Alex Lawrence18 янв. 2011 г., 10:56
Большое спасибо за этот подробный и хорошо изученный ответ! Несмотря на то, что теперь мне нужно подумать о другом способе проверки моей ситуации, полезно знать, что это ожидаемое поведение.

Ваш ответ на вопрос