2016-04-24 3 views
0

Посмотрел по всему Интернету, но, похоже, не нашел ответа на мою проблему. Я погружался в тестовые контроллеры в Laravel, используя PHPUnit и Mockery. Тем не менее, я, похоже, не считаю, что мои модели на основе Eloquent ошибочно выглядят. Мне удалось так же обмануть мой Auth :: user(), хотя это не используется в тесте ниже.Laravel 5 - Использование mockery для издевки яркой модели

Функция в AddressController, которая должна быть проверена:

public function edit($id) 
{ 
    $user = Auth::user(); 
    $company = Company::where('kvk', $user->kvk)->first(); 
    $address = Address::whereId($id)->first(); 

    if(is_null($address)) { 
     return abort(404); 
    } 

    return view('pages.address.update') 
     ->with(compact('address')); 
} 

ControllerTest, содержащей нАлАдкУ и имитационного метод

abstract class ControllerTest extends TestCase 
{ 
    /** 
    * @var \App\Http\Controllers\Controller 
    */ 
    protected $_controller; 

    public function setUp(){ 
     parent::setUp(); 
     $this->createApplication(); 
    } 

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

    protected function mock($class) 
    { 
     $mock = Mockery::mock($class); 
     $this->app->instance($class, $mock); 
     return $mock; 
    } 
} 

AddressControllerTest простирающейся ControllerTest

class AddressControllerTest extends ControllerTest 
{ 
    /** 
    * @var \App\Models\Address 
    */ 
    private $_address; 

    /** 
    * @var \App\Http\Controllers\AddressController 
    */ 
    protected $_controller; 

    public function setUp(){ 
     parent::setUp(); 
     $this->_controller = new AddressController(); 
     $this->_address = factory(Address::class)->make(); 
    } 

    public function testEdit404(){ 
     $companyMock = $this->mock(Company::class); 
     $companyMock 
      ->shouldReceive('where') 
      ->with('kvk', Mockery::any()) 
      ->once(); 
      ->andReturn(factory(Company::class)->make([ 
       'address_id' => $this->_address->id 
      ])); 

     $addressMock = $this->mock(Address::class); 
     $addressMock 
      ->shouldReceive('whereId') 
      ->with($this->_address->id) 
      ->once(); 
      ->andReturn(null); 

     //First try to go to route with non existing address 
     $this->action('GET', '[email protected]', ['id' => $this->_address->id]); 
     $this->assertResponseStatus(404); 
    } 
} 

Ошибки он держит бросание:

1) AddressControllerTest::testEdit404 
Mockery\Exception\InvalidCountException: Method where("kvk", object(Mockery\Matcher\Any)) from Mockery_1_Genta_Models_Company should be called exactly 1 times but called 0 times. 

Возможно, у кого-то есть идея?

+0

Заменил метод $ this-> call() с помощью метода $ this-> action(), проверяя, был ли вообще вызван мой метод контроллера, и это произошло после замены. Однако проблема сохраняется. –

ответ

5

Хорошо, после поиска нескольких сообщений Джеффри Пути (парень за Ларакастами), рекомендующих людям перестать насмехаться над Красноречивыми объектами и вместо этого использовать в базах памяти я пробовал этот подход. Я думал, что это, возможно, будет очень полезно для других пользователей, имеющих такие же проблемы в будущем, поэтому я объясню ниже.

Сейчас я редактировал мой файл «конфигурация/database.php» для поддержки параметра базы данных в оперативной памяти с использованием SQLite:

'sqlite' => [ 
      'driver' => 'sqlite', 
      'database' => ':memory:', 
      'prefix' => '', 
     ], 

Далее в верхней части файла, вы увидите следующую конфигурацию :

'default' => env('DB_CONNECTION', 'mysql'), 

Это может остаться такой же, это означает, что Laravel будет проверять переменные .env найти «DB_CONNECTION» или другое использование MySQL по умолчанию. Вероятно, это именно то, что вы хотели бы сделать, когда запускаете приложение как обычно. Однако при тестировании вы бы переопределили эту конфигурацию и временно изменили конфигурацию базы данных на «sqlite». Это может быть сделано путем добавления переменного «» DB_CONNECTION к вашему .env файла:

DB_CONNECTION=mysql 

Наконец в вашем phpunit.xml, конфигурационный файл, используемый для Laravel instantiatie модульных тестов, вы должны сказать, что при тестировании эта переменная должна быть установлена ​​в «SQLite»:

<env name="DB_CONNECTION" value="sqlite"/> 

Теперь вы сделали и Laravel запустится невидимый каждый раз базы данных в оперативной памяти, вы собираетесь идти тестирование. Не забудьте добавить следующую строку к тестам, которым нужна база данных.

use \Illuminate\Foundation\Testing\DatabaseMigrations; 

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

Таким образом, он отлично работает для меня! Надеюсь, вы, ребята, сможете это использовать.

+0

Прекрасно работает для меня. Благодарю. Я также высеваю DB после миграции.Просто предостережение: вы обнаружите, что нотация '@depends testCreateCard' не будет работать, скажем, Id от метода к методу, потому что' setUp() 'запускается один раз за тест, и DB будет сбрасываться каждый раз. Я решил, что засеял мои данные и использовал твердое значение. – mayid

Смежные вопросы