Если у вас есть объект CatController
, вы не должны насмехаться над ним в тесте, если это вообще возможно.Вы хотите проверить этот класс, поэтому используйте реальный класс.
Вы можете избавиться от всех вызовов "setMethod"
.По умолчанию все методы будут проверены, и это то, что вы хотите.
Существуют и другие библиотеки-насмешки, которые делают меньше насмешливых строк кода, таких как Phake
и Mockery
, которые нравятся некоторым людям, но у меня не слишком много личного опыта.
Чтомне кажется немного странным, что вы устанавливаете макеты, используя открытые свойства.Я ожидал, что они войдут в конструктор Controllers.
Учитывая, что это ваш метод, который можно сделать:
public function testAddCat()
{
$cat = $this->getMockBuilder('Default_Model_Cat')
->disableOriginalConstructor()
->getMock();
$workflow = $this->getMockBuilder('Default_Model_Workflow_Cat')
->disableOriginalConstructor()
->getMock();
$workflow->expects($this->once())
->method('addCat')
->with($cat);
$controller = new CatController(/*if you need params here pass them!*/);
// You can use this to avoid mocking the object if you want
// If your tests are more of a usage doc maybe don't
$controller->serviceExecutor = "My fake Executor";
$controller->catWorkflowFactory = $this->getMockBuilder('Factory')
->disableOriginalConstructor()
->getMock();
$controller->catWorkflowFactory->expects($this->once())
->method('create')
->with(array("My fake Executor"))
->will($this->returnValue($workflow));
$controller->addCat($cat);
}
Давайте рассмотрим некоторые общие вещи в настройке
Просто чтобы сделать каждую функцию более приятной для чтения, давайте возьмем макеты по умолчанию для установки.
public function setUp() {
$this->controller = new CatController(/*if you need params, pass them!*/);
$this->serviceExecutor = $this->getMockBuilder('ServiceExecutor')
->disableOriginalConstructor()
->getMock();
$this->controller->serviceExecutor = $this->serviceExecutor;
$this->cat = $this->getMockBuilder('Default_Model_Cat')
->disableOriginalConstructor()
->getMock();
$this->workflow = $this->getMockBuilder('Default_Model_Workflow_Cat')
->disableOriginalConstructor()
->getMock();
$this->controller->catWorkflowFactory = $this->getMockBuilder('Factory')
->disableOriginalConstructor()
->getMock();
}
и метод:
public function testAddCat()
{
$this->workflow->expects($this->once())
->method('addCat')
->with($this->cat);
$this->controller->catWorkflowFactory->expects($this->once())
->method('create')
->with(array($this->serviceExecutor))
->will($this->returnValue($this->workflow));
$this->controller->addCat($cat);
}
Это все еще не на самом деле красиво, но мы разделили его на более управляемые куски.
Программа установки создает все поддельные объекты, но ничего не делает (поэтому они не проваливают тест и время установки должно быть небрежным)
, в то время как тесты фокусируются на описании того, что должно произойти.
В общем, я бы сказал: "если это так сложно использовать класс, может быть, это хорошая вещь, тесты показывают, чтомного чего нужно сделать ". Если в этом проблема, возможно, поменять класс. Производителю, который его использует, также будет трудно все исправить. Но многие фреймворки / подходы делают спецификации контроллеровв этом отношении, чтобы вы знали лучше:)