视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
测试laravel commands的方法详解
2020-11-03 13:38:51 责编:小采
文档

引言

最近使用到laravel的consolo命令行工具,在编写命令,想写一些测试的时候,发现官方文档中并没有提到command的测试方法。花了点时间,找了资料,实践成功并记录一下,方便更多人。

推荐:《laravel教程》

测试方法

大家都知道Laravel中使用了很多Symfony的成熟组件,Laravel的console组件使用的就是Symfony/console。

幸运的是,Symfony/console 组件中提供了用于command测试的CommandTester, 使用方法如下

...
use FooCommand;
use SymfonyComponentConsoleApplication;
use SymfonyComponentConsoleTesterCommandTester;
...
public function testSample(){
 //创建一个console测试应用平台,用来搭载测试的命令
 $application = new Application();
 
 //创建待测试的command
 $testedCommand = $this->app->make(FooCommand::class);
 //设置命令执行需要的laravel依赖
 $testedCommand->setLaravel(app());
 //添加待测试的command到测试应用上
 //同时command 也绑定 application
 $application->add($testedCommand);
 //实例化命令测试类
 $commandTester = new CommandTester($testedCommand);
 //命令输入流,对应每次交互需要提供的输入内容
 $commandTester->setInputs([
 //...
 ]);
 //执行命令
 $commandTester->execute(['command' => $testedCommand->getName()]);
 //对命令执行结果进行断言测试,主要是依靠正则判断
 //$commandTester->getDisplay() 方法可以获取命令执行后的输出结果
 $this->assertRegExp("/some reg/", $commandTester->getDisplay());
}

示例

我们现在有一个手动创建新用户的命令createUser,作用就是手动创建一个用户。

需要交互式让用户输入name,email,password,comfirm password,这些数据。

待测试的command

<?php
namespace AppConsoleCommands;
use AppUser;
use IlluminateAuthEventsRegistered;
use IlluminateConsoleCommand;
use IlluminateSupportFacadesValidator;
class CreateUser extends Command
{
 /**
 * The name and signature of the console command.
 *
 * @var string
 */
 protected $signature = 'createUser';
 /**
 * The console command description.
 *
 * @var string
 */
 protected $description = 'create new user for system manually';
 /**
 * Create a new command instance.
 *
 * @return void
 */
 public function __construct()
 {
 parent::__construct();
 }
 /**
 * Execute the console command.
 *
 * @return mixed
 */
 public function handle()
 {
 $this->line($this->description);
 // 获取输入的数据
 $data = [
 'name' => $this->ask('What's your name?'),
 'email' => $this->ask('What's your email?'),
 'password' => $this->secret('What's your password?'),
 'password_confirmation' => $this->secret('Pleas confirm your password.')
 ];
 // 验证输入内容
 $validator = $this->makeValidator($data);
 if ($validator->fails()) {
 foreach ($validator->errors()->toArray() as $error) {
 foreach ($error as $message) {
 $this->error($message);
 }
 }
 return;
 }
 // 向用户确认输入信息
 if (!$this->confirm('Confirm your info: ' . PHP_EOL . 'name:' . $data['name'] . PHP_EOL . 'email:' . $data['email'] . PHP_EOL . 'is this correct?')) {
 return;
 }
 // 注册
 $user = $this->create($data);
 event(new Registered($user));
 $this->line('User ' . $user->name . ' successfully registered');
 }
 /**
 * Get a validator for an incoming registration request.
 *
 * @param array $data
 * @return IlluminateContractsValidationValidator
 */
 protected function makeValidator($data)
 {
 return Validator::make($data, [
 'name' => 'required|string|max:255|unique:users',
 'email' => 'required|string|email|max:255|unique:users',
 'password' => 'required|string|min:6|confirmed'
 ]);
 }
 /**
 * Create a new user instance after a valid registration.
 *
 * @param array $data
 * @return AppUser
 */
 protected function create($data)
 {
 return User::create([
 'name' => $data['name'],
 'email' => $data['email'],
 'password' => bcrypt($data['password'])
 ]);
 }
}

正确的结果

如果正确输入信息的话,会得到如下输出

$ path-to-your-app/app# php artisan createUser
create new user for system manually
 What's your name?:
 > vestin
 What's your email?:
 > correct@abc.com
 What's your password?:
 > 
 Pleas confirm your password.:
 > 
 Confirm your info: 
name:vestin
email:correct@abc.com
is this correct? (yes/no) [no]:
 > yes
User vestin successfully registered

想要测试的内容

我想要测试两块内容:

1.数据输入验证测试

● email有效性测试

● password两次输入是否相同的测试

2.正确创建用户测试

● 编写单元测试

<?php
namespace TestsUnitcommand;
use AppConsoleCommandsCreateUser;
use SymfonyComponentConsoleApplication;
use SymfonyComponentConsoleTesterCommandTester;
use TestsTestCase;
use IlluminateFoundationTestingRefreshDatabase;
class CreateUserTest extends TestCase
{
 use RefreshDatabase;
 /**
 * 测试数据验证
 *
 * @return void
 */
 public function testValidation()
 {
 $application = new Application();
 $testedCommand = $this->app->make(CreateUser::class);
 $testedCommand->setLaravel(app());
 $application->add($testedCommand);
 $commandTester = new CommandTester($testedCommand);
 $commandTester->setInputs(['Vestin', 'badEmail@abc', '123456', '654321']);
 $commandTester->execute(['command' => $testedCommand->getName()]);
 // assert
 $this->assertRegExp("/The email must be a valid email address/", $commandTester->getDisplay());
 $commandTester->setInputs(['vestin', 'correct@abc.com', '123456', '654321']);
 $commandTester->execute(['command' => $testedCommand->getName()]);
 // assert
 $this->assertRegExp("/The password confirmation does not match/", $commandTester->getDisplay());
 }
 /**
 * 测试成功注册用户
 *
 * @return void
 */
 public function testSuccess()
 {
 $application = new Application();
 $testedCommand = $this->app->make(CreateUser::class);
 $testedCommand->setLaravel(app());
 $application->add($testedCommand);
 $commandTester = new CommandTester($testedCommand);
 $commandTester->setInputs(['Vestin', 'correct@abc.com', '123456', '123456', 'y']);
 $commandTester->execute(['command' => $testedCommand->getName()]);
 // assert
 $this->assertRegExp("/User Vestin successfully registered/", $commandTester->getDisplay());
 $this->assertDatabaseHas('users', [
 'email' => 'correct@abc.com',
 'name' => 'Vestin'
 ]);
 }
}

执行测试

$ path-to-your-app/app# ./vendor/bin/phpunit 
PHPUnit 6.4.3 by Sebastian Bergmann and contributors.
.. 3 / 3 (100%)
Time: 659 ms, Memory: 14.00MB

下载本文
显示全文
专题