Laravel Artisan 服务中的控制台输出,同时可进行单元测试

Laravel Artisan console output in services, while unit testable

向从 artisan 命令 类.

调用的服务 类 添加控制台输出记录器的最佳做法是什么

示例代码:

<?php
class Import extends Command
{
    public function handle()
    {
            /** @var \Services\ServiceImport $service */
            $service = resolve($this->resolvers[$db])
                ->setCommand($this);

            # Console output
            $this->info(sprintf('Starting import for "%s"', $service::SERVICE_NAME));
            $imported = $service->import($this->argument('file'));

            $this->info(sprintf('Total rows imported: %d', $imported));
        }
    }
}

/** Different file, service from container */

class ServiceImport extends Service
{
    protected $cmd; 

    public function import($file)
    {
        # Need this console output
        $this->cmd->info(sprintf('Importing file "%s"', $file));
        // [...] More stuff goes on..this illustrates my point
    }

    public function setCommand(Command $cmd)
    {
        $this->cmd = $cmd;
        return $this;
    }
}

这行得通,但在尝试对 ServiceImport 进行单元测试时失败了,因为 $cmd 未设置...而且我还没有找到模拟 [=15= 的方法] 让这个工作,要么。我该如何做到这一点?

我确定我遗漏了什么。这是我使用服务的方式吗?我不可能是唯一一个在处理过程中查看 运行 常量 运行ning 详细日志的人。

使用 Laravel 5.4、artisan 命令。

我不想使用 Log::,因为我专门写入控制台(使用漂亮的 Symfony 颜色)。

因为您只想创建日志输出,您可以通过检查 null.

来解决这个问题

在您的服务中,只需使用函数参数注入命令依赖项,如下所示:

public function import($file, Command $cmd = null)
{
    # Need this console output
    if($cmd != null) {
        $this->cmd->info(sprintf('Importing file "%s"', $file));
    }
    // [...] More stuff goes on..this illustrates my point
}

在您的测试中,您可以轻松省略 $cmd 参数,因为这不会影响您的服务代码。

如果你过度使用这种输出,创建一个 Trait 或一个 base class,函数如下:

public function info(string $message, Command $cmd = null)
{
    if($cmd != null){
        $cmd->info($message);
    } else {
        //perhaps log message otherwise in test environment 
        // or when service is used outside of artisan commands
    }
}

而且您可以在服务的任何地方使用它

$this->info(sprintf('Importing file "%s"', $file), $cmd);