2016-04-24 18 views
0

インターネットを見渡しながらも、私の問題に対する答えは見つからないようです。私はPHPUnitとMockeryを使ってLaravelのコントローラをテストしています。しかし、私はEloquentベースのモデルが正しく嘲笑されていないようです。私はAuth :: user()を同じ方法でモックすることができましたが、これは以下のテストでは使用されていません。試験される必要があるAddressControllerでLaravel 5 - モクリーを使って擬似モデルを模擬する

機能:

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 - >アクション()メソッドでの$ this - >()メソッドの呼び出しを置き換え。しかし、問題は続く。 –

答えて

5

さて、ジェフリー・ウェイ(Laracastsの後ろの男)による複数の投稿を見つけ、私はそのアプローチを試してみた雄弁オブジェクトをからかっ停止し、代わりにインメモリデータベースを使用する人を推薦した後。私はこれがおそらく将来同じ問題を抱えている他のユーザーにとっては非常に役に立つと思ったので、以下で説明します。

今私はsqliteのを使用して、インメモリデータベースオプションをサポートするために、私の「設定/ database.phpで」ファイルを編集した:

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

次は、ファイルの先頭に次の設定が表示されます:

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

これは、同じ滞在することができ、それはLaravelは「DB_CONNECTION」を見つけるためにあなたの.env変数を確認したり、他のデフォルトとしてMySQLを使用することを意味します。これはおそらく、いつものようにアプリケーションを実行するときにやりたいことです。しかし、テストでは、この設定を無効にして、データベース設定を 'sqlite'に一時的に設定したいと考えています。これはあなたの.envファイルに「DB_CONNECTION」変数を追加することによって行うことができます。

DB_CONNECTION=mysql 

は、最後にあなたのphpunit.xml、ユニットテストをinstantiatieするLaravelが使用するコンフィギュレーションファイルには、テストするときにことを伝える必要がありますこの変数は、「sqliteを」に設定する必要があります。

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

は今、あなたが行われ、Laravelはあなたがテストを行ってしようとしている目に見えない、インメモリデータベース毎回起動します。データベースが必要なテストに次の行を追加することを忘れないでください。

use \Illuminate\Foundation\Testing\DatabaseMigrations; 

これは、テストを開始する前にLaravelがデータベースの移行を実行するため、通常どおりにテーブルを使用できるようにします。

それは私のために完璧に動作します。この方法!あなたたちがそれを使用できることを願っています。

+0

私のためにうまく動作します。ありがとう。私はまた、移行後にDBを播種しています。ちょっと警告: 'setUp()'がテストごとに1回実行され、毎回DBがリセットされるため、 '@depends testCreateCard'表記はメソッドからメソッドにIdを渡すようには動作しません。私はデータをシードし、ハードコードされた値を使用して解決しました。 – mayid