chkltlabs's avatar

My Service Provider is being ignored?

I wrote a custom service provider for an api service I am writing to access the Wix api. I have registered it in config/app.php, done the usual artisan config:clear and artisan cache:clear and composer dumpautoload, but when I call for resolve(Wix::class) or app(Wix::class), I get the following error:

1) Tests\Unit\Services\WixService\Resources\BlogTest::test_list_posts_live
Illuminate\Contracts\Container\BindingResolutionException: Unresolvable dependency resolving [Parameter #0 [ <required> string $api_key ]] in class App\Services\WixService\Wix

/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:1118
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:1027
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:958
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:920
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:770
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:706
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:120
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:777
/var/www/html/tests/Unit/Services/WixService/Resources/BlogTest.php:22

The call in BlogTest.php is simply $wix = resolve(Wix::class)

config/app.php

    'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
        Laravel\Passport\PassportServiceProvider::class,
        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\HorizonServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        App\Providers\TelescopeServiceProvider::class,

        // Barryvdh\Cors\ServiceProvider::class,
        Collective\Html\HtmlServiceProvider::class,

        // App\Providers\OpenCensusProvider::class,
        App\Providers\WixServiceProvider::class, //<<<<<<<<<<<<<<<<<
        App\Providers\PlaidServiceProvider::class,
        App\Providers\FilamentConfigurationProvider::class,
    ],

WixServiceProvider.php

<?php

namespace App\Providers;

use App\Services\WixService\Wix;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class WixServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Wix::class, function (){
            $w = new Wix(
                config('services.wix.key'),
                config('services.wix.host')
            );
            return $w;
        });
    }

    public function provides(): array
    {
        return [Wix::class];
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

The Wix class itself:

<?php

namespace App\Services\WixService;

//... imports omitted for brevity

class Wix
{
    public function __construct(
        public string $api_key,
        public string $api_host_url
    )
    {
        
    }
			//... other methods omitted for brevity
}

Any clue what I have missed here? I am developing on a Sail docker container if thats relevant.

0 likes
2 replies
chkltlabs's avatar

An update:

I opened up a tinker shell and ran app()->bound(App\Services\WixService\Wix::class), and it returned true.

Then, I added the same call inside a dd() at the beginning of the test in BlogTest.php, and it returned false.

So the issue is with my test setup.

BlogTest.php

<?php

namespace Tests\Unit\Services\WixService\Resources;

use App\Services\WixService\Wix;
use Tests\Unit\Services\WixService\TestCase;

class BlogTest extends TestCase
{
    public function test_list_posts_live(): void
    {
        //dd(app()->bound(\App\Services\WixService\Wix::class)); //returns false
        $wix = resolve(Wix::class); //throws error

        $response = $wix->blog->listPosts();

        dd($response);
    }
}

WixService\TestCase.php extends the phpunit base TestCase, and doesnt override anything relevant, i think?

<?php

namespace Tests\Unit\Services\WixService;

use Capsule\Request;
use Capsule\Response;
use PHPUnit\Framework\TestCase as PHPUnitTestCase;
use Shuttle\Handler\MockHandler;
use Shuttle\Shuttle;
use App\Services\WixService\Wix;

abstract class TestCase extends PHPUnitTestCase
{
    protected function getWixClient(
        //string $environment = "production" //may need later, unsure
        ): Wix
	{
		$httpClient = new Shuttle([
			'handler' => new MockHandler([
				function(Request $request) {

					$requestParams = [
						"method" => $request->getMethod(),
						"content" => $request->getHeaderLine("Content-Type"),
						"scheme" => $request->getUri()->getScheme(),
						"host" => $request->getUri()->getHost(),
						"path" => $request->getUri()->getPath(),
						"params" => \json_decode($request->getBody()->getContents()),
					];

					return new Response(200, \json_encode($requestParams));

				}
			])
		]);

		$wix = new Wix("key",
            "host"
        );
		$wix->setHttpClient($httpClient);

		return $wix;
	}
}
chkltlabs's avatar

Got it figured out, I was extending the base PHPUnit TestCase instead of the Laravel TestCase, which is what creates the application and binds services to the container.

Please or to participate in this conversation.