Skip to content

Instantly share code, notes, and snippets.

@mtvbrianking
Last active May 28, 2019 08:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mtvbrianking/6fc674354003510e39b76cdc62f74000 to your computer and use it in GitHub Desktop.
Save mtvbrianking/6fc674354003510e39b76cdc62f74000 to your computer and use it in GitHub Desktop.
Test artisan command consumes external API using service container injection.
interface ClientInterface
{
    public function request($method, $uri, $headers = [], $body = []);
}
class Client implements ClientInterface
{
    public function request($method, $uri, $headers = [], $body = [])
    {
        return json_encode(['status' => 'API may return successful | error feedback...']);
    }
}
class ServiceProvider extends AppServiceProvider
{
    public function register(): void
    {
        $this->app->bind(ClientInterface::class, Client::class);
    }
}
class ConsumeApiCommand extends Command
{
    public function __construct(ClientInterface $client)
    {
        parent::__construct();

        $this->client = $client;
    }

    public function handle()
    {
        $api_response = $this->client->request('POST', 'http://external.api/resource');

        $response = json_decode($api_response);

        if(isset($response['error'])) {
            $this->error($response['error']);
        } else {
            $this->info($response['status']);
        }
    }
}
class TestsServiceProvider extends AppServiceProvider
{
    public function register(): void
    {
        $this->app->bind(ClientInterface::class, function () {
            return new class implements ClientInterface {
                public function request($method, $uri, $headers = [], $body = [])
                {
                    return json_encode(['status' => "You've reached us."]);
                }
            };
        });
    }
}
trait CreatesApplication
{
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->register(TestsServiceProvider::class);
        
        $app->make(Kernel::class)->bootstrap();

        return $app;
    }
}
class ConsumeApiCommandTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        
        // Re-bootstrap artisan command
        $this->app->make(Kernel::class)->bootstrap();
    }

    public function test_can_consume_api_if_authenticated()
    {
        $this->artisan('consume:api')
             ->expectsOutput("You've reached us.")
             ->assertExitCode(0);
    }

    public function test_cant_consume_api_if_not_authenticated()
    {
        $this->app->bind(ClientInterface::class, function () {
            return new class implements ClientInterface {
                public function request($method, $uri, $headers = [], $body = [])
                {
                    return json_encode(['error' => "Unauthorized."]);
                }
            };
        });

        $this->artisan('consume:api')
             ->expectsOutput("Unauthorized.")
             ->assertExitCode(0);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment