jjzjj

php - 模拟静态 Eloquent 模型方法,包括 find()

coder 2024-04-20 原文

我一直在关注一般的 Mockery 和 PHP-Unit 教程 - 包括 Jeffrey Way 介绍的使用 PHP-Unit 和 Mockery 测试 Laravel。然而,对于这个应用程序——我们可以接受对 Eloquent 的依赖,而不是创建一个存储库类。

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

我读过 https://github.com/padraic/mockery/wiki#mocking-public-static-methods文档,并看到可以在要模拟的类前面放置一个“别名”前缀。但我似乎也无法让它发挥作用。

这是 routes.php...

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

这是(缩短的) Controller ...

<?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()

想法?

最佳答案

好的 - 删除了路由模型绑定(bind),并向模拟模型的 View 返回了一个对象。

Controller 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

关于php - 模拟静态 Eloquent 模型方法,包括 find(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19753502/

有关php - 模拟静态 Eloquent 模型方法,包括 find()的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  8. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  9. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  10. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

随机推荐