模拟静态雄辩模型 方法包括 find()


Mocking Static Eloquent Models Methods including find()

我一直在关注一般的 Mockery 和 PHP-Unit

教程 - 包括 Jeffrey Way 介绍用 PHP-Unit 和 Mockery 测试 Laravel。但是,对于这个应用程序 - 我们可以依赖 Eloquent 并且宁愿不创建存储库类。

我们能够很好地模拟 Widget 模型的实例方法。但是,我们使用的是 Route:model 绑定,我承认在测试控制器的 show($widget) 方法时,我不确定如何模拟模型的 find() 方法。

我已经阅读了 https://github.com/padraic/mockery/wiki#mocking-public-static-methods 文档,并看到可以将"别名"前缀放在要被嘲笑的类前面。但我似乎也无法让它工作。

这是路线.php...

Route::model('widgets', 'Widget');
Route::resource('widgets', 'WidgetController');

这是(缩短的)控制器...

<?php
/*
|--------------------------------------------------------------------------
| Widget Controller
|--------------------------------------------------------------------------
|
| An example controller that uses the pre-baked RESTful resource controller
| actions for index, create, store, show, edit, update, destroy, as well as a
| delete method to show the record before deletion.
|
| See routes.php  ->
| Route::resource('widget', 'WidgetController');
| Route::get('widget/{widget}/delete', 'WidgetController@delete');
|
*/
class WidgetController extends BaseController
{
    /**
     * Widget Model
     * @var Widget
     */
    protected $widget;
    /**
     * Inject the model.
     * @param Widget $widget
     */
    public function __construct(Widget $widget)
    {
        parent::__construct();
        $this->widget = $widget;
    }
    /**
     * Display a listing of the resource.
     *
     * See public function data() below for the data source for the list,
     * and the view/widget/index.blade.php for the jQuery script that makes
     * the Ajax request.
     *
     * @return Response
     */
    public function index()
    {
        // Title
        $title = Lang::get('widget/title.widget_management');
        // Show the page
        return View::make('widget/index', compact('title'));
    }
    /**
     * Show a single widget details page.
     *
     * @return View
     */
    public function show($widget)
    {
        // Title
        $title = Lang::get('widget/title.widget_show');
        // Show the page
        return View::make('widget/show', compact('widget', 'title'));
    }
    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {
        // Title
        $title = Lang::get('widget/title.create_a_new_widget');
        // Show the page
        return View::make('widget/create', compact('title'));
    }
    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store()
    {
        // Validate the inputs
        $rules = array(
            'name'=> 'required|alpha_dash|unique:widgets,name',
            'description'=> 'required'
            );
        // Validate the inputs
        $validator = Validator::make(Input::all(), $rules);
        // Check if the form validates with success
        if ($validator->passes()) {
            // Get the inputs, with some exceptions
            $inputs = Input::except('csrf_token');
            $this->widget->name = $inputs['name'];
            $this->widget->description = $inputs['description'];
            $this->widget->save($rules);
            if ($this->widget->id) {
                // Redirect to the new widget page
                return Redirect::to('widgets')->with('success', Lang::get('widget/messages.create.success'));
            } else {
                // Redirect to the widget create page
                //var_dump($this->widget);
                return Redirect::to('widgets/create')->with('error', Lang::get('widget/messages.create.error'));
            }
        } else {
            // Form validation failed
            return Redirect::to('widgets/create')->withInput()->withErrors($validator);
        }
    }
}

这是测试夹具。

# /app/tests/controllers/WidgetControllerTest.php
class WidgetControllerTest extends TestCase
{
    public function __Construct()
    {
        $this->mock = Mockery::mock('Eloquent', 'Widget');
    }
    public function setUp()
    {
        parent::setUp();
        $this->app->instance('Widget', $this->mock);
    }
    public function tearDown()
    {
        Mockery::close();
    }
    /**
     * Index
     */
    public function testIndex()
    {
        $this->call('GET', 'widgets');
        $this->assertTrue($this->client->getResponse()->isOk());
        $this->assertViewHas('title');
    }
    /**
     * Show
     */
    public function testShow()
    {
        //$this->mock->shouldReceive('find')->with(1)->once()->andReturn(array('id'=>1));
        $this->mock
        ->shouldReceive('find')
        ->once()
        ->andSet('id', 1);
        //$this->call('GET', 'widgets/1');
        $this->action('GET', 'WidgetController@show', array(
            'widgets' => 1
            ));
        $this->assertTrue($this->client->getResponse()->isOk());
    }
    /**
     * Create
     */
    public function testCreate()
    {
        $crawler = $this->client->request('GET', 'widgets/create');
        $this->assertTrue($this->client->getResponse()->isOk());
        $this->assertViewHas('title');
        $this->assertCount(1, $crawler->filter('h3:contains("Create a New Widget")'));
    }
    /**
     * Store Success
     */
    public function testStoreSuccess()
    {
        $this->mock
        ->shouldReceive('save')
        ->once()
        ->andSet('id', 1);
        $this->call('POST', 'widgets', array(
            'name' => 'Fu-Widget',
            'description' => 'Widget description'
            ));
        $this->assertRedirectedToRoute('widgets.index');
    }
    /**
     * Store Fail
     */
    public function testStoreFail()
    {
        $this->call('POST', 'widgets', array(
            'name' => '',
            'description' => ''
            ));
        $this->assertRedirectedToRoute('widgets.create');
        $this->assertSessionHasErrors(['name']);
    }
}

testShow 方法上的错误是:调用未定义的方法 Widget::find()

思潮?

好的 - 删除了路由模型绑定,并将一个对象返回到模拟模型的视图。

控制器https://github.com/58bits/laravel-4-bootstrap-3-starter/blob/master/app/controllers/WidgetController.php

测试https://github.com/58bits/laravel-4-bootstrap-3-starter/blob/master/app/tests/controllers/WidgetControllerTest.php