Внедрение зависимости Laravel в издевательстве

Я пытаюсь написать тест для этого репо: laravel.com. ниже представлена ​​структура приложения.

Приложение \ Documentation.php

public function __construct(Filesystem $files, Cache $cache)
{
   $this->files = $files;
   $this->cache = $cache;
}

public function get($version, $page)
{
    return $this->cache->remember('docs.'.$version.'.'.$page, 5, function () use ($version, $page) {
    
            if ($this->files->exists($path = $this->markdownPath($version, $page))) {
                return $this->replaceLinks($version, markdown($this->files->get($path)));
            }

            return null;
    });
}

public function markdownPath($version, $page)
{
    return base_path('resources/docs/'.$version.'/'.$page.'.md');
}

DocsController.php

public function __construct(Documentation $docs)
{
     $this->docs = $docs;
}

public function show($version, $page = null)
{
    $content = $this->docs->get($version, $sectionPage);
}

вот моя тестовая логика

$mock = Mockery::mock('App\Documentation')->makePartial();

$mock->shouldReceive('markdownPath')->once()->andReturn(base_path('test/stubs/stub.md'));

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

$this->get('docs/'.DEFAULT_VERSION.'/stub') //It hits DocsController@show
//...

вот ошибка

Вызов функции-члена Remember () при нулевом значении

Разные способы, которые я пробовал до сих пор, и разные ошибки

1)

$mock = \Mockery::mock('App\Documentation');

$mock->shouldReceive('markdownPath')->once()->andReturn(base_path('test/stubs/stub.md'));

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

Mockery \ Exception \ BadMethodCallException: получено Mockery_0_App_Documentation :: get (), но ожидания не указаны

Здесь я не хочу определять ожидания для каждого метода.

2)

app()->instance('App\Documentation', \Mockery::mock('App\Documentation[markdownPath]', function ($mock) {
    $mock->shouldReceive('markdownPath')->once()->andReturn(base_path('test/stubs/stub.md'));
}));

ArgumentCountError: слишком мало аргументов для функции App \ Documentation :: __ construct (), 0 передано и ровно 2 ожидаемых

Если мы укажем имя метода в mock (App \ Documentation [markdownPath]); конструктор не насмешливый, поэтому мы получаем ошибку.


person AmirRezaM75    schedule 29.12.2019    source источник


Ответы (1)


Вы можете использовать контейнер для разрешения реального экземпляра (чтобы были разрешены зависимости файловой системы и кеша), а затем создать частичный макет из вашего реального экземпляра, чтобы определить ожидания для метода markdownPath. Как только ваш макет будет настроен, поместите его в контейнер для использования контроллером.

// Resolve a real instance from the container.
$instance = $this->app->make(\App\Documentation::class);

// Create a partial mock from the real instance.
$mock = \Mockery::mock($instance);

// Define your mock expectations.
$mock->shouldReceive('markdownPath')->once()->andReturn(base_path('test/stubs/stub.md'));

// Put your mock instance in the container.
$this->app->instance(\App\Documentation::class, $mock);
person patricus    schedule 29.12.2019
comment
Tanx для обратной связи, но в этом случае markdownPath не вызывается из mock Method markdownPath(<Any Arguments>) from Mockery_0_App_Documentation_App_Documentation should be called exactly 1 times but called 0 times. Я использовал dd () в markdownPath, и он выполняет фактический код - person AmirRezaM75; 30.12.2019
comment
@ AmirRezaM75 Возможно, что метод get() обнаруживает попадание в кеш, что означает, что ваш метод markdownPath() никогда не будет вызван. В качестве быстрого теста просто закомментируйте функцию кеширования в вашем контроллере и посмотрите, выполнено ли фиктивное ожидание. - person patricus; 31.12.2019