FriendsOfPHP / Goutte

Goutte, a simple PHP Web Scraper
MIT License
9.26k stars 1.01k forks source link

Re-add getClient/setClient? #444

Open marbuser opened 3 years ago

marbuser commented 3 years ago

I really disagree with the move away from Guzzle, but I can at least understand some of the reasons.

However, I can't understand why setClient/getClient was removed. It made writing tests and mocking with this package infinitely easier, and the new api is incredibly unintuitive, no offense.

Ever since the move away from Guzzle, integrating this package has become way more work with frameworks like Laravel. Sure you can achieve basic stuff easily, but the second it comes to actually trying to mock/fake anything, it becomes an incredibly tedious and frustrating API to work with where I'm starting to feel just writing my own scraper from scratch would be a better option. From personal experience, I never got this with older versions of Goutte that supported Guzzle. It was a dream to work with back then.

Using old versions isn't an option, because Laravel literally prevents you from even installing it due to a Guzzle version constraint.

Livijn commented 2 years ago

It's actually pretty ease to mock the response with Laravel and Goutte. Here is how I did it.

AppServiceProvider.php:

class AppServiceProvider extends ServiceProvider
{
    // ...
    public function register()
    { 
        // ...
        app()->bind(HttpClient::class, function () {
            return HttpClient::create();
        });
    }

Service.php:

class Service
{
    public function refreshProductsForCategory(ProductCategory $category)
    {
        $client = new Client(app()->make(HttpClient::class));
        $crawler = $client->request('GET', $category->url);
        // ...
    }
}

ServiceTest.php:

class ServiceTest extends TestCase
{
    /** @test It can blabla */
    public function it_can_blabla()
    {
        $this->mockClient();
        $service = new Service();
        $service->perform();
        // Perform checks
    }

    private function mockClient()
    {
        $callback = function ($method, $url, $options) {
            return new MockResponse('the html response here');
        };

        $client = new MockHttpClient($callback);

        app()->bind(HttpClient::class, fn () => $client);
    }