Intereting Posts
Как сделать разбиение на страницы из массива? Как создать архив Phar без индекса Определение ориентации EXIF ​​и поворот изображения с помощью ImageMagick jqgrid пользовательские данные JSON отсутствуют, но не отображаются данные Конкретный столбец не вставлен при сохранении записи Composer Autoload – Не удается найти класс CakeEmail в cakephp 2 может отправлять электронную почту одному и тому же smtp, но не swiftmailer в laravel разрывы строк в текстовом поле Как отправить данные из MYSQL / PHP в компонент Coldfusion? Предоставить загрузочную папку для этих разрешений безопасно или нет? Устранение неполадок «Ошибка разделителя не должна быть буквенно-цифровой или обратной косой чертой» при изменении ereg () на preg_match () Можно ли сохранить знаки плюса в PHP $ _GET без кодирования? JQuery, перетаскивание и сохранение в базу данных mysql? Как отправлять и получать данные с Visual Basic на PHP? Эффективность электронной почты PHP (BCC против отдельных сообщений электронной почты)

PHPUnit проверяет метод, возвращающий свойство объектов

public function thisMethod { $example = $this->methodReturnsObject()->this1->that2->there3->id; return $example; } 

Как бы вы протестировали этот метод в PHPUnit?

Очевидно, я мог бы написать, что методReturnsObject () вернет что-то … но что? У этого объекта есть свойства, связанные с ним, но как бы вы даже издевались над этим значением?

Ответ «Ты не делаешь». Тестирование модулей должно тестировать каждый класс отдельно, то, что вы пытаетесь сделать, не является единичным тестом. Как я сказал в своем комментарии, вы нарушаете Закон Деметры , в котором просто говорится:

  • Каждое подразделение должно иметь только ограниченное знание других единиц: только единицы «тесно» связаны с текущим устройством.
  • Каждое устройство должно разговаривать только со своими друзьями; не разговаривайте с незнакомцами.
  • Только поговорите со своими ближайшими друзьями.

У вас есть тесно связанные классы, которые нуждаются в повторном факторинге. Сначала я написал классы, чтобы проиллюстрировать этот момент, но я обычно пишу тесты в первую очередь.

Давайте начнем с конца цепочки: –

 class there3 { private $id public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } } 

Теперь давайте создадим для него единичный тест: –

 class there3Test extends PHPUnit_Framework_TestCase { public function testCanGetId() { $there3 = new there3(); $there3->setId(3); $this->assertTrue($there3->getId() === 3); } } 

Этот класс теперь протестирован, поэтому нам не нужно его снова тестировать. Теперь давайте посмотрим на следующий: –

 class this2 { public $there3; //To facilitate unit testing we inject the dependency so we can mock it public function __construct(there3 $there3) { $this->there3 = $there3; } public function getId() { return $this->there3->getId(); } } 

И теперь единичный тест: –

 class this2Test extends PHPUnit_Framework_TestCase { public function testCanGetId() { $mockThere3 = $this->getMock('there3'); $mockThere3->method('getId') ->will($this->returnValue(3); $this2 = new this2($mockThere3);//We pass in the mock object instead of the real one $this->assertTrue($this2->getId() === 3); } } 

Мы сделаем последний пример, чтобы еще раз проиллюстрировать мою мысль:

 class this1 { private $this2; public function __construct(this2 $this2)//injecting again { $this->$this2 = $this2; } public function getId() { return $this->$this2->getId(); } } 

И, опять же, единичный тест: –

 class this1Test extends PHPUnit_Framework_TestCase { public function testCanGetId() { $mockThis2 = $this->getMock('this2'); $mockThis2->method('getId') ->will($this->returnValue(3); $this1 = new this1($mockThis2);//We pass in the mock object instead of the real one $this->assertTrue($this1->getId() === 3); } } 

Надеюсь, вы получите идею без меня, чтобы пройти через все объекты в вашем примере.

То, что я сделал, – это отделить классы друг от друга. Они знают только об объекте, от которого они зависят, им все равно, как этот объект получает запрошенную информацию.

Теперь вызов id будет выглядеть примерно так:

 public function getId() { return $this->this1->getId(); } 

Который пойдет вверх по цепочке, пока не вернется id2: id. Вам никогда не придется писать что-то вроде $ this -> $ this1 -> $ this2-> there3-> id, и вы можете правильно тестировать свои классы.

Для получения дополнительной информации об модульном тестировании см. Руководство PHPUnit .

Как бы вы протестировали thisMethod в PHPUnit, я бы:

  1. старайтесь избегать попадания в точку, где единичный тест издевается над 3+ вложенными частями
  2. создать случайную версию объекта и проверить, что случайность одинакова

Такие как:

 <?php // an opaque known $random = rand(); // the results $value = new stdClass(); $value->this1 = new stdClass(); $value->this1->this2 = new stdClass(); $value->this1->this2->there3 = new stdClass(); $value->this1->this2->there3->id = $random; // somehow get the known value into the fixture // not enough detail shown about $this->methodReturnsObject() // to make a reasonable suggestion about it. $this->assertEquals( $random, $this->fixture->thisMethod(), "Got a value from somewhere else" ); 

Используйте метод rrehbein для построения возвращаемого значения из метода макета и создания частичного макета любого класса, содержащего thisMethod и methodReturnsObjectmethodReturnsObject класс. Mock methodReturnsObject чтобы вернуть созданный объект $value .

Предполагая, что класс называется Foo дает

 function testThisMethod() { $foo = $this->getMock('Foo', array('methodReturnsObject')); $value = // create as rrehbein demonstrated $foo->expects($this->once()) ->method('methodReturnsObject') ->will($this->returnValue($value)); self::assertSame($value, $foo->thisMethod()); }