JohnnyC
JohnnyC

Reputation: 1435

Test static method that call another from same class

I have a class:

namespace Models;

use Contracts\PathContract;

class Path implements PathContract
{
    public static function getStorage(string $type): string
    {
        return storage_path(config('logs.storage_path', 'logs'))
            .DIRECTORY_SEPARATOR
            .$type;
    }
    
    public static function directoryExists(string $type): bool
    {
        var_dump(Path::getStorage($type)); // output: .../logs/vendor/orchestra/testbench-core/laravel/storage/logs/myCustomType
        if (is_dir(self::getStorage($type))) {
            return true;
        }

        return false;
    }
}

I would like test directoryExists static method:

public function testDirectoryExists(): void
{
    $path = Mockery::mock(Path::class)->makePartial();
    $path->shouldReceive('getStorage')
        ->once()
        ->andReturn('/var/log');

    var_dump($path::getStorage('blah blah blah')); // output: /var/log

    $this->assertTrue($path::directoryExists('myCustomType'));
}

From directoryExists method, getStorage method doesn't return mock value but return real value. Any ideas ?

How can I test a static method that call another from same class ?

Upvotes: 0

Views: 898

Answers (1)

Maksim
Maksim

Reputation: 2957

No no no. You MUST mock dependencies, not testing code. Static function is bad design for testing.

If the functions weren't static, you could use Filesystem and mock them.

In this case, the best way is to mock the directory by using temp.

public function testDirectoryExists(): void
{
    //prepare
    $temp = sys_get_temp_dir();
    $logsPath = 'logs';
    $logsDir = $temp.DIRECTORY_SEPARATOR.$logsPath;
    $type = 'someType';
    mkdir($logsDir);

    //mock
    $this->app->useStoragePath($temp);
    config()->set('logs.storage_path', $logsPath);

    //assert not created
    $this->assertFalse(Path::directoryExists($type));

    //assert created
    mkdir($logsDir.DIRECTORY_SEPARATOR.$type);
    $this->assertTrue(Path::directoryExists($type));
}

Updated

Or, if you use Laravel, you can use File facade:

public static function directoryExists(string $type): bool
{
    return File::isDirectory(self::getStorage($type));
}
public function testDirectoryExists(): void
{
    $type = 'myType';
    $expectedDir = '/logs/vendor/orchestra/testbench-core/laravel/storage/logs/'.$type;

    $mock = Mockery::mock(\Illuminate\Filesystem\Filesystem::class);
    $mock->shouldReceive('isDirectory')
        ->with($expectedDir)
        ->andReturn(true);

    $this->app->instance(\Illuminate\Filesystem\Filesystem::class, $mock);

    $this->assertTrue(Path::directoryExists($type));
}

Upvotes: 2

Related Questions