2014-09-11 6 views
1

Я разрабатываю PHP (5.4.25) приложение с laravel (4.2) рамки. Я хотел бы проверить свою UserController с издевательством, поэтому я приспосабливать свою UserController таким образом:Laravel mock with Mockery Eloquent модели

class UsersController extends \BaseController { 
    protected $user; 

    public function __construct(User $user) { 
     $this->user = $user; 
     $this->beforeFilter('csrf', array('on'=>'post')); 
    } 

    public function store() { 
     $validator = Validator::make(Input::all(), User::$rules); 

     if ($validator->passes()) { 
      $this->user->username = Input::get('username'); 
      $this->user->password = Hash::make(Input::get('password')); 
      $this->user->first_name = Input::get('first_name'); 
      $this->user->last_name = Input::get('last_name'); 
      $this->user->email = Input::get('email'); 
      $this->user->save(); 


      return true; 
     } else { 
      return false; 
     } 
    } 

Я хочу, чтобы макет модели Eloquent пользователя, поэтому я развивать свою UsersControllerTest так:

class UsersControllerTest extends TestCase { 

    private $mock; 

    public function __construct() {} 

    public function setUp() { 
     parent::setUp(); 

     $this->createApplication();              
    } 

    public function tearDown() { 
     parent::tearDown(); 

     Mockery::close(); 
    } 

    public function testStore() { 
     $this->mock = Mockery::mock('Eloquent','User[save]');           
     $this->mock 
      ->shouldReceive('save') 
      ->once() 
      ->andReturn('true');               
     $this->app->instance('User', $this->mock);          

     $data['username'] = 'qwerety'; 
     $data['first_name'] = 'asd'; 
     $data['last_name'] = 'asd123'; 
     $data['email'] = '[email protected]'; 
     $data['password'] = 'password'; 
     $data['password_confirmation'] = 'password'; 

     $response = $this->call('POST', 'users', $data); 

     var_dump($response->getContent()); 
    } 

} 

Когда я запускаю свой тест, он возвращает мне эту ошибку:

Mockery\Exception\InvalidCountException : Method save() from Mockery_0_User should be called 
exactly 1 times but called 0 times. 

Почему? Что не так?

EDIT: Я нашел проблему - Если я не использую фиктивный объект все отлично работает и контроллер создания нового пользователя в БД, но когда я использую макет метод Input:all() возвращает пустой массив.

- Благодаря

ответ

1

Проблема была в $this->createApplication();.

Я прокомментировал, что строка и Input::all() отлично работают со всеми входными параметрами!

1

Как вы проверяете это, в конструкторе контроллера передается экземпляр реальных красноречивых моделей, а не притворные. Если вы хотите протестировать фасады (как четко указано в documentation), вы должны вызвать метод shouldReceive() непосредственно на фасаде, чтобы он издевался.

Но, так как вы переосмысление $this->user переменных в store() методы контроллера, он не будет называться, если вы не удалите жёстко прописанный экземпляр и использовать впрыскиваются $user.

Редактировать: я пропускаю линию $this->app->instance('User', $this->mock);. Таким образом, проблема может быть связана с тем, что в методе store вы получаете экземпляр нового класса напрямую, а не через контейнер Laravel IoC. вместо $this->user = new User; в вашем методе магазина, вы должны получить его через App::make('User');

+0

Также удалив экземпляр нового класса в методе хранилища, который я понес в той же ошибке. – PapaSmurf

1

я имел такую ​​же проблему, когда я начал испытывать ..... вещи есть то, что, в методе UsersController магазина вы на самом деле сохранения пользователя к базе данных и базе вашего кода это может сработать нормально, но вы удивляетесь, что на самом деле это не проходит тест. Теперь подумайте об этом так, чтобы ты глумился пользователем, и вы сказали, тесту, что когда-либо я называю модель пользователя, пожалуйста, дайте мне фиктивную версию моего пользователя, как вы делали в вашей строке коды ниже

$this->app->instance('User', $this->mock); 

Теперь проблема заключается в том, что вам необходимо также назвать фиктивную версию Save() методом от тестовой модели версии пользователя, как так:

$this->mock->save(); 

Рассмотрит следующий пример:

public function testStore() 
{ 
    $input = ['name', 'Canaan']; 

    $this->mock 
     ->shouldReceive('create') 
     ->once()->with($input); 

    $this->app->instance('User', $this->mock); 
    $this->mock->create($input); 

    $this->call('POST', 'users', $input); 

} 

Надеюсь, это поможет вам.

+0

Если я не использую mock-объект, все работает нормально, и контроллер создает нового пользователя в БД, но когда я использую mock, метод 'Input: all()' возвращает пустой массив. – PapaSmurf

+0

Не побеждает ли логика, чтобы снова вызвать класс $ this-> mock-> create ($ input) 'в классе тестирования. Для меня я чувствую, что это обманывает тест и заставляет его пройти тест контроллера, что означает, что тест пройдет независимо от того, был ли в контроллере (тот, который был протестирован), вызов '$ this-> user- > сохранить(); ' –

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