2014-10-10 5 views
1

Я просмотрел буквально сотни страниц, и я не могу найти, что отличает мою ситуацию от рабочих примеров, которые я нашел на этих страницах.Mocking the Eloquent Model

Я использую Laravel 4.2, PHPUnit 4.3.1 и последнюю версию Mockery от Composer. Я запускаю тест PHPUnit на своем контроллере, AppController, и я хотел бы перехватить резервную базу данных Eloquent(), издеваясь над моделью. Хотя при создании Mock ошибок не возникает, макет также не привязан к моей модели, поэтому строки все еще создаются.

Что мне здесь не хватает? Благодаря!

Моя ошибка с издевательством: Mockery\Exception\InvalidCountException: Method save() from Mockery_0_EventRsvp should be called exactly 1 times but called 0 times.

// Located at /app/tests/app/AppControllerTest.php 
class AppControllerTest extends TestCase { 
    public function setUp() { 
     parent::setUp(); 
     Session::start(); 
     Mail::pretend(); 
    } 
    public function tearDown() { 
     parent::tearDown(); 
     \Mockery::close(); 
    } 
    public function testPostApp() { 
     $myvar = array(); 
     $this->mock = \Mockery::mock('Eloquent','EventRsvp'); 
     $this->app->instance('EventRsvp', $this->mock); 
     $this->mock 
       ->shouldReceive('save') 
       ->once() 
       ->andReturn('true'); 
     $response = $this->call('POST', '/3tDYSL0', $myvar); 
    } 
} 

// Located at /app/controllers/AppController 
class AppController extends BaseController { 
    public function saveApp($shortUrl){ 
     $rsvp = new EventRsvp; 
     $rsvp->fieldone = '124'; 
     $rsvp->fieldtwo = '30233'; 
     $rsvp->save(); 

     $returnredirect = Redirect::to(Request::path(). '/complete'); 
     return $returnredirect; 
    } 
} 

// Located at /app/models/EventRsvp.php 
<? 
class EventRsvp extends Eloquent { 

    protected $guarded = array('id'); 
    use Illuminate\Database\Eloquent\SoftDeletingTrait; 
    protected $dates = ['deleted_at']; 

    public function relationshipone() 
    { 
     return $this->belongsTo('RelationshipOne','idone'); 
    } 

    public function relationshiptwo() 
    { 
     return $this->belongsTo('RelationshipTwo','idtwo'); 
    } 

} 
?> 
+3

Ваш код является примером не проверяемого. Читайте об инъекции зависимостей и о том, почему «плохо» использовать «новый класс» в вашем контроллере. Вы не можете ссылаться на этот «новый класс», насмехаясь, вам нужно вводить макет на ваш контроллер. –

+0

@JarekTkaczyk Хм, после прочтения, да, ты прав. Вся моя кодовая база написана таким образом, похоже, что у меня большая задача передо мной. Можете ли вы ответить на свой комментарий? Выглядит достаточно хорошо, чтобы отметить как ответ на меня. –

ответ

3

Использование dependency injection вместо вызова new EventRsvp.

Возможно, вы захотите создать репозиторий, который предоставит EventRsvp s вашему контроллеру, тогда вы можете легко высмеять репо и ввести его вместо реального.

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

$mock = Mockery::mock('overload:EventRsvp'); 
$mock->shouldReceive('save')->once()->andReturn(true); 

$response = $this->call('POST', '/3tDYSL0', $myvar); 

Это экземпляра насмешливого с издевательством, и он будет ловить new EventRsvp вызов в вашем контроллер, и используйте это $mock вместо реальной модели. Но опять же, используйте инъекцию зависимости, это то, что вы хотите.

+0

Спасибо за предоставление обходного пути - потребуется некоторое время, чтобы преобразовать всю мою кодовую базу, чтобы использовать DI, поэтому мне придется использовать обходной путь, пока я это делаю. Однако, когда я использую «перегрузку», как вы показывали, я получаю эту ошибку: «PHP Fatal error: вызов функции-члена mockery_getExpectations() для не-объекта». У кого-то еще в Google, похоже, есть эта проблема ... любая идея? –

+0

Ok - добавлен путь, поэтому теперь его 'Mockery :: mock ('overload: app \ models \ EventRsvp');' и это работает без ошибок 'mockery_getExpectations()' или моих исходных ошибок! Тем не менее, строка EventRsvp все еще создается. Как я могу это предотвратить? –

+0

Похоже, что добавление 'overload:' не относится к вызову 'once()', и поэтому оригинальное исключение больше не существует. Если я изменю макет на то, чего не существует, например 'Mockery :: mock ('overload: adsfadsf'),' тест по-прежнему выполняется без ошибок, хотя этот метод никогда не вызывается в контроллере. –