【问题标题】:How to test, with Mockery, a controller that uses an Ardent Model?如何使用 Mockery 测试使用 Ardent 模型的控制器?
【发布时间】:2013-12-26 21:43:00
【问题描述】:

我正在尝试在 Laravel 控制器中测试此功能:

/**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store()
    {
        $project = $this->project->create(Input::all());
        if ( $errors = $project->errors()->all() ) {
           return Redirect::route('projects.create')
           ->withInput()
           ->withErrors($errors);

       }
       return Redirect::route('projects.index')
       ->with('flash', Lang::get('projects.project_created'));

   }

我的(错误的)测试如下所示:

public function testStoreFails()
    {
        $this->mock->shouldReceive('create')
            ->once()
            ->andReturn(Mockery::mock(array(
                    false,
                    'errors' => array()
                    )));
        $this->call('POST', 'projects');
        $this->assertRedirectedToRoute('projects.create');
        $this->assertSessionHasErrors();
    }

问题基本上是,当验证失败时,Ardent 将 $project 设置为 false,但它也会在同一对象上设置错误,可以使用 ->errors()->all() 检索。

我很迷茫,试图找出在模拟中返回什么。

注意:构造函数注入模型:

public function __construct(Project $project)
    {
        $this->project = $project;

        $this->beforeFilter('auth');
    }

【问题讨论】:

    标签: testing laravel mocking mockery ardent


    【解决方案1】:

    – 由以下 cmets 编辑 –

    如果我理解您正在尝试正确执行的操作,您可以这样做:

    • 模拟create() 方法以返回模拟的Project
    • 模拟save() 方法返回false。
    • 模拟MessageBag 实例,这是errors() 将返回的对象。这个模拟应该有一个模拟的all() 方法。
    • 使模拟的errors() 方法返回MessageBag 模拟。

    假设 $this->mockProject 类的模拟:

    // given that $this->mock = Mockery::mock('Project')
    
    public function testStoreFails()
    {
        // Mock the create() method to return itself
        $this->mock->shouldReceive('save')->once()->andReturn(false); 
    
        // Mock MessageBag and all() method
        $errors = Mockery::mock('Illuminate\Support\MessageBag');
        $errors->shouldReceive('all')->once()->andReturn(array('foo' => 'bar'));
    
        // Mock errors() method from model and make it return the MessageBag mock
        $this->mock->shouldReceive('errors')->andReturn($errors);
    
        // Proceed to make the post call
        $this->call('POST', 'projects');
        $this->assertRedirectedToRoute('projects.create');
        $this->assertSessionHasErrors();
    }
    

    【讨论】:

    • PHP 致命错误:在第 43 行的 /dumminvoicing/app/controllers/ProjectsController.php 中的非对象上调用成员函数 errors()
    • 我猜create方法不能只返回false,因为在这种情况下不能调用errors方法。
    • 好的,有道理。我在你的问题中读到它被返回为假,我很困惑。尝试编辑答案,我已将 create() 模拟移动到函数顶部并更改了返回值。在模拟errors() 时,我还删除了once(),因为我认为withErrors() 方法可能会再次调用它......以防万一。
    • 我得到同样的错误:S 感谢您的帮助,我认为我们至少更接近了。也许它过早地调用错误,或者类似的东西?
    • 也许测试仍然以错误的方式编写,但是查看 Ardent 的代码,没有任何“创建”方法,我也无法在他们的文档中找到任何参考。也许所有代码都应该使用“保存”方法运行。
    猜你喜欢
    • 2019-09-10
    • 2014-06-15
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    • 2010-11-11
    • 2019-04-15
    相关资源
    最近更新 更多