【问题标题】:Test static method that call another from same class测试从同一个类调用另一个的静态方法
【发布时间】:2021-10-11 09:20:36
【问题描述】:

我有一堂课:

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;
    }
}

我要测试directoryExists静态方法:

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'));
}

directoryExists 方法,getStorage 方法不返回模拟值而是返回真实值。有什么想法吗?

如何测试从同一类调用另一个静态方法的静态方法?

【问题讨论】:

  • 不可能模拟/更改硬连线(静态)调用的实现。你应该改用依赖注入,因为这样你可以在你的模拟类中交换。

标签: php laravel phpunit mockery


【解决方案1】:

不不不。 您必须模拟依赖项,而不是测试代码。 静态函数是不好的测试设计。

如果函数不是静态的,您可以使用Filesystem 并模拟它们。

在这种情况下,最好的方法是使用tempmock 目录。

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

更新

或者,如果你使用 Laravel,你可以使用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));
}

【讨论】:

  • 使用文件外观在 Laravel 上下文中工作,但我认为这个问题更笼统。
  • 他使用 storage_patch() - 它是 laravel :) 但你是对的,更新了
  • 谢谢!确实,我使用 Laravel,但采用通用用例非常棒
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-28
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多