【问题标题】:Laravel Artisan console output in services, while unit testable服务中的 Laravel Artisan 控制台输出,同时可单元测试
【发布时间】:2017-10-31 09:33:07
【问题描述】:

将控制台输出记录器添加到从工匠命令类调用的服务类中的最佳做法是什么。

示例代码:

<?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...而且我还没有想出一种方法来模拟Command 使其正常工作。我该如何做到这一点?

我确定我错过了一些东西。这是我使用服务的方式吗?我不可能是唯一一个希望在处理过程中持续运行详细日志的人。

使用 Laravel 5.4,artisan 命令。

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

【问题讨论】:

    标签: php laravel console phpunit laravel-artisan


    【解决方案1】:

    由于您只想创建日志输出,您可以通过检查 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 或具有以下功能的基类:

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

    【讨论】:

    • 是的。你说得对。接近我发现的解决方案。我所做的是通过 AbstractCommand 类注入 $cmd ,并为其覆盖 run() 。我使用了 Partyline (statamic.com/blog/partyline) 作为一种方法,但是制作了一个完整的 PSR Logger,我可以将其注入 Monolog 堆栈。完美运行。更多信息:redd.it/6j42h5
    猜你喜欢
    • 2018-08-27
    • 2020-08-03
    • 1970-01-01
    • 2014-01-02
    • 2016-01-07
    • 2022-06-14
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多