试图在我的控制器测试中用IoC容器交换一个模型,但对象没有交换


Trying to swap a model in my controller test with IoC Container, but object not swapper

在测试时,我正试图使用IoC Container来交换我的Question模型。尽管我已经创建了一个mock模型,并在测试过程中使用App::instance()尝试交换依赖关系,但我可以从var_dump中看到它不起作用。我的代码出了什么问题?

<?php
class QuestionsControllerTest extends TestCase {
    protected $mock;
    public function __construct()
    {
        // This is how Net tuts tutorial instructed, but 
        // I got Eloquent not found errors
        // $this->mock = Mockery::mock('Eloquent', 'Question');
        // so I tried this instead, and it created the mock
        $this->mock = Mockery::mock('App'Question'); 
    }
    public function tearDown()
    {
        Mockery::close();
    }
    public function testQuestionIndex()
    {
        // var_dump(get_class($this->mock)); exit; // outputs: Mockery_0_App_Question
        // var_dump(get_class($this->app)); exit; // outputs: Illuminate'Foundation'Application
       $this->mock
           ->shouldReceive('latest')
           ->once()
           ->andReturnSelf();
        $this->mock
            ->shouldReceive('get') //EDIT: should be get
            ->once()
            ->andReturn('foo');
    $this->app->instance('App'Question', $this->mock);

        // dispatch route
        $response = $this->call('GET', 'questions');
        $this->assertEquals(200, $response->getStatusCode());
    }
}

到目前为止还不错吗?以下是我的问题控制器:

class QuestionsController extends Controller {
    protected $question;
    public function index(Question $question)
    {
        // var_dump(get_class($question)); exit; // Outputs App'Question when testing too
        $questions = $question
            ->latest()
            ->get();
        return view('questions.index', compact('questions'));
    }
    ...

因此,在没有交换对象的情况下,它无论如何都不会注册对方法的调用:

Mockery'Exception'InvalidCountException: Method latest() from Mockery_0_App_Question should be called
 exactly 1 times but called 0 times.

顺便说一下,我已经安装了Mockery~0.9、Laravel 5.0和PHPUnit~4.0。真的非常感谢在这方面的任何帮助。

我认为在使用instance()时需要指定完整的命名空间。否则,Laravel将假定模型在全局命名空间中('''Question')。

这应该有效:

$this->app->instance('App'Question', $this->mock);

现在关于另一个问题,你的模拟。既然你的观点想要一个集合,为什么不给它一个呢?如果你不想测试视图,你可以简单地实例化一个空集合并返回:

$this->mock
     ->shouldReceive('latest')
     ->once()
     ->andReturnSelf();
$this->mock
     ->shouldReceive('get')
     ->once()
     ->andReturn(new Illuminate'Database'Eloquent'Collection);

如果你愿意,你也可以检查视图是否正确接收到变量:

$response = $this->call('GET', 'questions');
$this->assertViewHas('questions');

由于您没有完全定义mock,因此会出现此错误。

您告诉mock,它应该期望latest被调用一次,但您没有指定最新应该返回的内容。在控制器的下一条线路上,您可以呼叫get

尝试以下代码

    $this->mock
       ->shouldReceive('latest')
       ->once()
       ->andReturnSelf();

     $this->mock
       ->shouldReceive('get') //EDIT: should be get
       ->once()
       ->andReturn('foo');
    $this->app->instance('Question', $this->mock);

关于在larvel中测试控制器的非常好的文章http://code.tutsplus.com/tutorials/testing-laravel-controllers--net-31456