ArtisanCommandTest.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. namespace Illuminate\Tests\Integration\Testing;
  3. use Illuminate\Support\Facades\Artisan;
  4. use Mockery;
  5. use Mockery\Exception\InvalidCountException;
  6. use Mockery\Exception\InvalidOrderException;
  7. use Orchestra\Testbench\TestCase;
  8. use PHPUnit\Framework\AssertionFailedError;
  9. class ArtisanCommandTest extends TestCase
  10. {
  11. protected function setUp(): void
  12. {
  13. parent::setUp();
  14. Artisan::command('survey', function () {
  15. $name = $this->ask('What is your name?');
  16. $language = $this->choice('Which language do you prefer?', [
  17. 'PHP',
  18. 'Ruby',
  19. 'Python',
  20. ]);
  21. $this->line("Your name is $name and you prefer $language.");
  22. });
  23. Artisan::command('slim', function () {
  24. $this->line($this->ask('Who?'));
  25. $this->line($this->ask('What?'));
  26. $this->line($this->ask('Huh?'));
  27. });
  28. }
  29. public function test_console_command_that_passes()
  30. {
  31. $this->artisan('survey')
  32. ->expectsQuestion('What is your name?', 'Taylor Otwell')
  33. ->expectsQuestion('Which language do you prefer?', 'PHP')
  34. ->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')
  35. ->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')
  36. ->assertExitCode(0);
  37. }
  38. public function test_console_command_that_passes_with_repeating_output()
  39. {
  40. $this->artisan('slim')
  41. ->expectsQuestion('Who?', 'Taylor')
  42. ->expectsQuestion('What?', 'Taylor')
  43. ->expectsQuestion('Huh?', 'Taylor')
  44. ->expectsOutput('Taylor')
  45. ->doesntExpectOutput('Otwell')
  46. ->expectsOutput('Taylor')
  47. ->expectsOutput('Taylor')
  48. ->assertExitCode(0);
  49. }
  50. public function test_console_command_that_fails_from_unexpected_output()
  51. {
  52. $this->expectException(AssertionFailedError::class);
  53. $this->expectExceptionMessage('Output "Your name is Taylor Otwell and you prefer PHP." was printed.');
  54. $this->artisan('survey')
  55. ->expectsQuestion('What is your name?', 'Taylor Otwell')
  56. ->expectsQuestion('Which language do you prefer?', 'PHP')
  57. ->doesntExpectOutput('Your name is Taylor Otwell and you prefer PHP.')
  58. ->assertExitCode(0);
  59. }
  60. public function test_console_command_that_fails_from_missing_output()
  61. {
  62. $this->expectException(AssertionFailedError::class);
  63. $this->expectExceptionMessage('Output "Your name is Taylor Otwell and you prefer PHP." was not printed.');
  64. $this->ignoringMockOnceExceptions(function () {
  65. $this->artisan('survey')
  66. ->expectsQuestion('What is your name?', 'Taylor Otwell')
  67. ->expectsQuestion('Which language do you prefer?', 'Ruby')
  68. ->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')
  69. ->assertExitCode(0);
  70. });
  71. }
  72. public function test_console_command_that_fails_from_exit_code_mismatch()
  73. {
  74. $this->expectException(AssertionFailedError::class);
  75. $this->expectExceptionMessage('Expected status code 1 but received 0.');
  76. $this->artisan('survey')
  77. ->expectsQuestion('What is your name?', 'Taylor Otwell')
  78. ->expectsQuestion('Which language do you prefer?', 'PHP')
  79. ->assertExitCode(1);
  80. }
  81. public function test_console_command_that_fails_from_unordered_output()
  82. {
  83. $this->expectException(InvalidOrderException::class);
  84. $this->ignoringMockOnceExceptions(function () {
  85. $this->artisan('slim')
  86. ->expectsQuestion('Who?', 'Taylor')
  87. ->expectsQuestion('What?', 'Danger')
  88. ->expectsQuestion('Huh?', 'Otwell')
  89. ->expectsOutput('Taylor')
  90. ->expectsOutput('Otwell')
  91. ->expectsOutput('Danger')
  92. ->assertExitCode(0);
  93. });
  94. }
  95. /**
  96. * Don't allow Mockery's InvalidCountException to be reported. Mocks setup
  97. * in PendingCommand cause PHPUnit tearDown() to later throw the exception.
  98. *
  99. * @param callable $callback
  100. * @return void
  101. */
  102. protected function ignoringMockOnceExceptions(callable $callback)
  103. {
  104. try {
  105. $callback();
  106. } finally {
  107. try {
  108. Mockery::close();
  109. } catch (InvalidCountException $e) {
  110. // Ignore mock exception from PendingCommand::expectsOutput().
  111. }
  112. }
  113. }
  114. }