用于PHPunit的Laravel 5.4模型模拟

时间:2017-04-09 23:08:08

标签: eloquent phpunit laravel-5.4 mockery

这是我第一次使用Mockery for PHPUnit。我按照此论坛中的示例进行操作,但仍然收到此错误:

  

Mockery \ Exception \ InvalidCountException:方法all()来自   应该正好调用Mockery_0_App_Card 1次,但调用0   次。

基本上,我在我的控制器中注入了我的模型。像这样:

class CardController extends Controller
{   
    protected $repository;

    function __construct(Model $repository)
    {
        $this->repository = $repository;
    }

    public function index()
    {

       $data = $this->repository->all();
       return $data;
    }
}

尝试这样的测试:

class CardTest extends TestCase
{
    protected $mock;

    protected function setUp(): void
    {
        parent::setUp();

        $this->mock = Mockery::mock('Model', '\App\Card');
    }

    public function testCardsList()
    {

        $this->mock->shouldReceive('all')
                    ->once()
                    ->andReturn(json_encode([[
                        "id"=> 1,
                        "name"=> "Aut modi quasi corrupti.",
                        "content"=> "..."
                        ],
                        [
                        "id"=> 2,
                        "name"=> "Voluptas quia distinctio.",
                        "content"=> "..."
                    ]]));            

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

        $response = $this->json('GET', $this->api.'/cards');
        $this->assertEquals(200, $response->status(), 'Response code must be 200');    
    }
}

我尝试了几种变体,但它总是一样的。比如,在控制器中设置Mockery或使用Card :: class表示法。任何线索?

另外,我确定响应是从数据库中提取数据而不是使用我提供的数组。因此,Mockery对我的模型没有任何影响。

1 个答案:

答案 0 :(得分:1)

经过一些阅读后,我确信使用 SQLite 数据库进行测试比为模型创建模型更好。你不必那么多工作来创建模型。我正在链接到一些关于如何实现测试环境的讨论主题,但我也粘贴了我最终编写的代码。

基本上,您必须将DB配置为SQLite。你会声明它会在内存中运行。这比使用文件要快得多。

然后,您要运行迁移。就我而言,还有种子数据库。

<?php

namespace Tests;

use DirectoryIterator;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    protected function setUp()
    {
        parent::setUp();

        Config::set('database.connections.sqlite.database', ':memory:');
        Config::set('database.default', 'sqlite');

        Artisan::call('migrate');
        Artisan::call('db:seed');

    protected function tearDown()
    {
        Artisan::call('migrate:reset');
        parent::tearDown();
    }
}

有一点需要注意:setUp()每次测试都会被调用一次。我发现这种表示法不起作用,因为DB每次都会重新生成: @depends testCreateCard

我使用该表示法将ID从testCreate()传递给其他几种方法。但最终信任我的种子并使用硬编码值。

参考文献:

  1. Laravel 5 - Using Mockery to mock Eloquent model
  2. https://www.patrickstephan.me/post/setting-up-a-laravel-5-test-database.html
  3. https://laracasts.com/discuss/channels/testing/how-to-specify-a-testing-database-in-laravel-5
  4. https://laracasts.com/discuss/channels/general-discussion/how-to-migrate-a-testing-database-in-laravel-5