0

コントローラーが期待するリポジトリをモックすることで、Laravel 4 コントローラーの単体テストを行っています。問題は「ストア」機能にあります。これは、指定されたコントローラーに POST を実行するときに Laravel によって呼び出される関数です。関数が呼び出されitemDataますが、入力として期待されていますが、それを提供する方法がわかりません。これが私が試したことです:

ItemEntryController

class ItemEntryController extends BaseController
{
    protected $itemRepo;

    public function __construct(ItemEntryRepositoryInterface $itemRepo)
    {
        $this->itemRepo = $itemRepo;
    }

    public function store()
    {
        if(Input::has('itemData'))
        {
            $data = Input::get('itemData');

            return $this->itemRepo->createAndSave($data);
        }
    }
}

テストクラス

<?php

use \Mockery as m;

class ItemEntryRouteAndControllerTest extends TestCase {

protected $testItemToStore = '{"test":12345}';

public function setUp()
{
    parent::setUp();
    $this->mock = $this->mock('Storage\ItemEntry\ItemEntryRepositoryInterface');
}

public function mock($class)
{
    $mock = m::mock($class);
    $this->app->instance($class, $mock);

    return $mock;
}

public function testItemStore()
{
    Input::replace($input = ['itemData' => $this->testItemToStore]);

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

    $this->call('POST', 'api/v1/tools/itementry/items');
}
4

1 に答える 1

2

さて、いくつかのオプションがあります。

統合テスト

単体テスト docsに従うことをお勧めします。実際には、これらcall()すべてを設定できるメソッドがあります。これにより、アプリがブートストラップされ、データベースなどが使用されます。

これは、実際のクラス実装を使用するため、単体テストというよりも統合テストです。

単体テスト コントローラー実際にはあまり意味がない可能性があるため、これは実際には望ましい場合があります (理論的にはあまり機能しませんが、既に単体テスト済みの他のクラスを呼び出します)。しかし、これは単体テスト、統合テスト、受け入れテスト、およびそこに適用されるすべてのニュアンスになります。(よく読んで!)

単体テスト

実際に単体テストを検討している場合は、コントローラーを単体テスト可能にする必要があります (ha!)。これは (おそらく) すべての依存関係を注入することを意味します。

class ItemEntryController extends BaseController
{
    protected $itemRepo;

    // Not pictured here is actually making sure an instance of
    // Request is passed to this controller (via Service Provider or
    // IoC binding)
    public function __construct(ItemEntryRepositoryInterface $itemRepo, Request $input)
    {
        $this->itemRepo = $itemRepo;
        $this->request = $input;
    }

    public function store()
    {
        if($this->input->has('itemData'))
        {
            // Get() is actually a static method so we use
            // the Request's way of getting the $_GET/$_POST variables
            // see note below!
            $data = $this->input->input('itemData');

            return $this->itemRepo->createAndSave($data);
        }
    }
}

補足:Inputファサードは、実際には追加の静的メソッドを持つ Request オブジェクトのインスタンスget()です!

Input を使用しなくなり、Request オブジェクトを注入するようになったので、Request オブジェクトをモックすることで、このクラスを単体テストできます。

それが役立つことを願っています!

于 2013-08-14T21:36:15.460 に答える