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

时间:2017-05-30 19:13:40

标签: php laravel console phpunit artisan

将控制台输出记录器添加到从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没有设置......而且我还没有找到一种方法来模拟Command 1}}让这个工作。我该如何做到这一点?

我确定我错过了什么。我是如何使用服务的?我不能成为唯一一个在处理期间运行持续运行详细日志的人。

使用Laravel 5.4,artisan命令。

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

1 个答案:

答案 0 :(得分: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);