2015-08-03 4 views
2

Я пытаюсь узнать, как использовать Mockery с Laravel 5. Я основывал свои усилия в основном на книге Пути (Laravel Testing Decoded) и других учебниках, в которых говорится о интеграции [с PHPUnit] требуется только метод tearDown(). Поэтому я включил это. Проблема в том, что это не похоже на сброс вещей между тестами. Содержание моего тестового класса выглядит примерно так:Mockery false positive в тесте контроллера Laravel

public function __construct() 
{ 
    $this->mock = Mockery::mock('Class\To\Mock'); 
} 

public function tearDown() 
{ 
    Mockery::close(); 
} 

public function test_RedirectWithoutAuthentication() 
{ 
    // Act 
    $this->call('GET', '/path/1'); 

    // Assert 
    $this->assertRedirectedTo('/auth/login'); 
} 

public function test_X() 
{ 
    // Arrange 
    $this->mock->shouldReceive('MockedClassMethod')->once(); 

    // Act 
    $this->call('GET', '/path/1'); 
} 

Первые тестовые работы и промежуточное ПО Auth выталкивают пользователя на страницу входа. В интересах TDD, я написал второй тест, прежде чем MockedClassMethod на самом деле написан. Таким образом, к моему способу мышления, это должно быть неудачно эффектно. Но это не так. Он проходит!

Если я изменю порядок испытаний, он «работает» (неписаный сбой, auth pass), что заставляет меня думать, что это не проблема порядка, но что-то общее с одним тестом, который не очищается до следующий.

Любое понимание спасет оставшиеся волосы от вытаскивания. :-)

+0

Вы пытались поместить определение mockery mock в метод установки вместо конструктора? – Matteo

+0

Можете ли вы попытаться заменить 'public function __construct()' на 'protected function setUp()'? – Matteo

ответ

2

I попытался использовать метод setUp(), как описано Matteo, и это заставило тесты вообще не запускаться. Поэтому я отказался от этого курса, думая, что я ушел. Но предложение Маттео обратило меня к этому.

Немного вникая в , почему вызвало неудачные тесты, показал, что объект $ app никогда не создавался. Хм ... Итак, тогда мне стало понятно, что метод setUp() был , переопределяя некоторые важные вещи. Поэтому, чтобы исправить это, нужно было сначала вызвать родительский метод! Вроде так:

public function setUp() 
{ 
    parent::setUp(); 
    $this->mock = Mockery::mock('Class\To\Mock'); 
} 

С этого момента функции setUp() и tearDown() работали должным образом.

Я все еще не уверен, почему все примеры, которые я, кажется, обнаруживаю, показывают, что макет создается в конструкторе. Может быть, я все еще ничего не получаю, но, по крайней мере, он работает ... пока. :-)

+0

Привет, Джаред! Я не знал, что ваш тестовый класс имеет иерархию с уже реализованным методом 'setup'. Счастлив, что отлично работает! Удачи! – Matteo

+0

Спасибо, миллион. Мне не потребовалось бы времени, чтобы вернуться к setUp() без вашего предложения. Одна из тех вещей, которые вы проводите весь день, и это прямо перед вами ... – LavaWings

+0

привет @jared, добро пожаловать! пожалуйста, рассмотрите вопрос о моем ответе, если считаете это полезным – Matteo

2

В аккордеона с PHPUnit doc:

Методы шаблоном setUp() и tearDown() запускается один раз для каждого тестового метода (и на свежих экземплярах) класса тестового примера.

Конструктор вызывается только в первый раз, так что tearDown вызывается перед вторым испытанием, выполненным в классе, и эффект заключается в том, что экземпляр издевательства был закрыт.

Чтобы решить вашу проблему, вы можете использовать метод установки для инициализации издевавшегося объекта. Так замените конструктор класса тестового класса с помощью метода установки, как следующие:

Попробуйте использовать это:

protected function setUp() 
{ 
    $this->mock = Mockery::mock('Class\To\Mock'); 
} 

вместо:

public function __construct() 
{ 
    $this->mock = Mockery::mock('Class\To\Mock'); 
} 

Надеется, что это помощь