2025-01-28 17:14:49 -06:00
|
|
|
<?php
|
2024-09-13 20:20:19 -05:00
|
|
|
|
2025-01-28 17:33:54 -06:00
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
2024-09-13 20:20:19 -05:00
|
|
|
namespace Tests;
|
|
|
|
|
|
|
|
|
|
use App\Interfaces\MarketData\AlphaVantageMarketData;
|
2025-01-28 17:14:49 -06:00
|
|
|
use App\Interfaces\MarketData\FallbackInterface;
|
2024-10-29 16:34:18 -05:00
|
|
|
use App\Interfaces\MarketData\Types\Quote;
|
2025-01-28 17:14:49 -06:00
|
|
|
use App\Interfaces\MarketData\YahooMarketData;
|
2025-04-09 19:25:15 -05:00
|
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
2025-01-28 17:14:49 -06:00
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
use Mockery;
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
class FallbackInterfaceTest extends TestCase
|
|
|
|
|
{
|
2025-04-09 19:25:15 -05:00
|
|
|
use RefreshDatabase;
|
|
|
|
|
|
2025-01-28 17:14:49 -06:00
|
|
|
protected function setUp(): void
|
2024-09-13 20:20:19 -05:00
|
|
|
{
|
|
|
|
|
parent::setUp();
|
|
|
|
|
|
|
|
|
|
Log::spy();
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 17:14:49 -06:00
|
|
|
public function test_fallback_to_next_provider_on_failure()
|
2024-09-13 20:20:19 -05:00
|
|
|
{
|
|
|
|
|
config()->set('investbrain.provider', 'yahoo,alphavantage');
|
|
|
|
|
config()->set('investbrain.interfaces', [
|
|
|
|
|
'yahoo' => YahooMarketData::class,
|
|
|
|
|
'alphavantage' => AlphaVantageMarketData::class,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$yahooMock = Mockery::mock(YahooMarketData::class);
|
|
|
|
|
$yahooMock->shouldReceive('quote')
|
2025-01-28 17:14:49 -06:00
|
|
|
->andThrow(new \Exception('Yahoo failed'));
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$alphaMock = Mockery::mock(AlphaVantageMarketData::class);
|
|
|
|
|
$alphaMock->shouldReceive('quote')
|
2025-04-09 19:25:15 -05:00
|
|
|
->andReturn(new Quote([
|
|
|
|
|
'name' => 'Test Quote',
|
|
|
|
|
'symbol' => 'ACME',
|
|
|
|
|
'currency' => 'USD',
|
|
|
|
|
'market_value' => 10,
|
|
|
|
|
]));
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$this->app->instance(YahooMarketData::class, $yahooMock);
|
|
|
|
|
$this->app->instance(AlphaVantageMarketData::class, $alphaMock);
|
|
|
|
|
|
2025-01-28 17:14:49 -06:00
|
|
|
$fallbackInterface = new FallbackInterface;
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$result = $fallbackInterface->quote('ACME');
|
|
|
|
|
|
2025-04-09 19:25:15 -05:00
|
|
|
$this->assertEquals(new Quote([
|
|
|
|
|
'name' => 'Test Quote',
|
|
|
|
|
'symbol' => 'ACME',
|
|
|
|
|
'currency' => 'USD',
|
|
|
|
|
'market_value' => 10,
|
|
|
|
|
]), $result);
|
2024-09-13 20:20:19 -05:00
|
|
|
|
2025-04-09 19:25:15 -05:00
|
|
|
Log::shouldHaveReceived('error')->with('Failed calling method quote for ACME (yahoo): Yahoo failed');
|
2024-09-13 20:20:19 -05:00
|
|
|
}
|
|
|
|
|
|
2025-01-28 17:14:49 -06:00
|
|
|
public function test_all_providers_fail()
|
2024-09-13 20:20:19 -05:00
|
|
|
{
|
|
|
|
|
config()->set('investbrain.provider', 'yahoo,alpha');
|
|
|
|
|
config()->set('investbrain.interfaces', [
|
|
|
|
|
'yahoo' => YahooMarketData::class,
|
|
|
|
|
'alphavantage' => AlphaVantageMarketData::class,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$yahooMock = Mockery::mock(YahooMarketData::class);
|
|
|
|
|
$yahooMock->shouldReceive('quote')
|
2025-01-28 17:14:49 -06:00
|
|
|
->andThrow(new \Exception('Yahoo failed'));
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$alphaMock = Mockery::mock(AlphaVantageMarketData::class);
|
|
|
|
|
$alphaMock->shouldReceive('quote')
|
2025-01-28 17:14:49 -06:00
|
|
|
->andThrow(new \Exception('Alpha failed'));
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$this->app->instance(YahooMarketData::class, $yahooMock);
|
|
|
|
|
$this->app->instance(AlphaVantageMarketData::class, $alphaMock);
|
|
|
|
|
|
2025-01-28 17:14:49 -06:00
|
|
|
$fallbackInterface = new FallbackInterface;
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$this->expectException(\Exception::class);
|
2025-04-09 19:25:15 -05:00
|
|
|
$this->expectExceptionMessage('Could not get market data calling method quote: Provider [alpha] is not a valid market data interface.');
|
2024-09-13 20:20:19 -05:00
|
|
|
|
|
|
|
|
$fallbackInterface->quote('AAPL');
|
|
|
|
|
|
2025-04-09 19:25:15 -05:00
|
|
|
Log::shouldHaveReceived('error')->with('Failed calling method quote for AAPL (yahoo): Yahoo failed');
|
|
|
|
|
Log::shouldHaveReceived('error')->with('Failed calling method quote for AAPL (alpha): Alpha failed');
|
2024-09-13 20:20:19 -05:00
|
|
|
}
|
2025-01-28 20:32:43 -06:00
|
|
|
|
|
|
|
|
public function test_exists_method_fails_without_exception()
|
|
|
|
|
{
|
|
|
|
|
config()->set('investbrain.provider', 'yahoo,alpha');
|
|
|
|
|
config()->set('investbrain.interfaces', [
|
|
|
|
|
'yahoo' => YahooMarketData::class,
|
|
|
|
|
'alphavantage' => AlphaVantageMarketData::class,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$yahooMock = Mockery::mock(YahooMarketData::class);
|
|
|
|
|
$yahooMock->shouldReceive('exists')
|
|
|
|
|
->andThrow(new \Exception('Yahoo failed'));
|
|
|
|
|
|
|
|
|
|
$alphaMock = Mockery::mock(AlphaVantageMarketData::class);
|
|
|
|
|
$alphaMock->shouldReceive('exists')
|
|
|
|
|
->andThrow(new \Exception('Alpha failed'));
|
|
|
|
|
|
|
|
|
|
$this->app->instance(YahooMarketData::class, $yahooMock);
|
|
|
|
|
$this->app->instance(AlphaVantageMarketData::class, $alphaMock);
|
|
|
|
|
|
|
|
|
|
$fallbackInterface = new FallbackInterface;
|
|
|
|
|
|
|
|
|
|
$result = $fallbackInterface->exists('ZZZ');
|
|
|
|
|
|
2025-01-28 20:33:28 -06:00
|
|
|
$this->assertIsBool($result);
|
2025-01-28 20:32:43 -06:00
|
|
|
$this->assertFalse($result);
|
|
|
|
|
}
|
2025-01-28 17:14:49 -06:00
|
|
|
}
|