0
votes

I'm trying to write test for this repo: laravel.com. below is the app's structure.

App\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);
}

here is my test logic

$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
//...

here is the error

Call to a member function remember() on null

Different ways I've tried so far and different errors

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: Received Mockery_0_App_Documentation::get(), but no expectations were specified

Here I don't wanna define expectation for each methods.

2)

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

ArgumentCountError: Too few arguments to function App\Documentation::__construct(), 0 passed and exactly 2 expected

If we specify method name in mock (App\Documentation[markdownPath]); the constructor is not mocking, so we get error.

1

1 Answers

0
votes

You can use the container to resolve a real instance (so that the filesystem and cache dependencies are resolved), and then create a partial mock from your real instance in order to define the expectation for the markdownPath method. Once your mock instance is setup, put it into the container for the controller to use.

// 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);