You have an additional "i" here..
iinterface ApiConfigurationInterface
Hi everyone.
I'm stuck with the next problem.
I writing an external API client. It depends on the configuration interface that provides some configuration parameters like endpoints, tokens, etc.
API client class:
class ApiClient
{
private $apiConfiguration;
public function __construct(ApiConfigurationInterface $apiConfiguration)
{
$this->apiConfiguration = $apiConfiguration;
}
API configuration interface:
interface ApiConfigurationInterface
{
public function getToken();
public function getEndpoint();
public function getProxy();
}
In the service provider I bind appropriate class to this interface:
public function register()
{
$this->app->bind(ApiConfigurationInterface::class, ApiConfiguration::class);
}
And it works fine.
Also, I wrote some tests for my API client. In the tests I would like to substitute production configuration class to stub class that also implements configuration interface. This will enable me to provide API client fake parameters and API client will use mock external API providing directly in tests.
For achieve it, I added the condition to service provider that checks environment and binds different configuration interface implementations:
public function register()
{
if ($this->app->environment('testing')) {
$this->app->bind(ApiConfigurationInterface::class, FakeApiConfiguration::class);
} else {
$this->app->bind(ApiConfigurationInterface::class, ApiConfiguration::class);
}
}
That's fake configuration class:
class FakeApiConfiguration implements ApiConfigurationInterface
{
public function getToken()
{
return 'token';
}
public function getEndpoint()
{
return 'http://localhost:9999/endpoint';
}
public function getProxy()
{
return null;
}
}
In the test class I use service container to inject API client.
class ApiClientTest extends TestCase
{
use HttpMockTrait;
private $apiClient;
...
public function setUp()
{
$this->setUpHttpMock();
app()->make(ApiClient::class);
}
}
And that's the problem: when I try to perform tests, PHPUnit fails with next messag:
Illuminate\Contracts\Container\BindingResolutionException : Target [App\Services\ApiClients\ApiClient\Configuration\ApiConfigurationInterface] is not instantiable while building [App\Services\ApiClients\ApiClient\ApiClient].
I tried to delete conditions from service provider to check if they are the source of the problem:
public function register()
{
$this->app->bind(ApiConfigurationInterface::class, FakeApiConfiguration::class);
}
But I have no changes. PHPUnit message is the same.
I tried also dirty trick: create TestClass instance in the test controller and call test from here. And it works without errors.
class TestController extends Controller
{
public function test()
{
$test = new ApiClientTest();
ApiClientTest::setUpBeforeClass();
$test->setUp();
$test->someTest();
}
}
I cannot understand why service container does not bind and instantiate appropriate class to API configuration interface while running tests. I spent a lot of time to solve that problem. But could not find a resolution.
Please help to solve it.
parent::setUp() when overriding setUp method.AppServiceProvider:
public function register()
{
$this->app->bind(ApiConfigurationInterface::class, ApiConfiguration::class);
}
Test:
class ApiClientTest extends TestCase
{
use HttpMockTrait;
private $apiClient;
public function setUp()
{
parent::setUp();
$this->setUpHttpMock();
$this->app->bind(ApiConfigurationInterface::class, FakeApiConfiguration::class);
$this->apiClient = $this->app->make(ApiClient::class);
}
/** @test */
public function example()
{
dd($this->apiClient);
}
}
Result after running example test:
App\ApiClient^ {#355
-apiConfiguration: Tests\FakeApiConfiguration^ {#356}
}
Please or to participate in this conversation.