Installation
composer require deozza/philarmony-api-tester-bundle
Add the bundle to config/bundles.php:
return [
// ...
Deozza\PhilarmonyApiTesterBundle\PhilarmonyApiTesterBundle::class => ['all' => true],
];
Database Setup
.env.test (or .env for local testing).doctrine/doctrine-fixtures-bundle to load test fixtures:
composer require orm-fixtures
tests/ApplicationFixtures (see Folder Structure).First Test Case
Create a test class in tests/Api (e.g., tests/Api/UserTest.php):
namespace Tests\Api;
use Deozza\PhilarmonyApiTesterBundle\Test\ApiTestCase;
class UserTest extends ApiTestCase
{
public function testGetUsers()
{
$response = $this->get('/api/users');
$this->assertEquals(200, $response->getStatusCode());
}
}
Run tests:
php bin/phpunit
Test Structure
ApplicationFixtures (e.g., UserFixtures).
// src/DataFixtures/ORM/UserFixtures.php
public function load(ObjectManager $manager)
{
$user = new User();
$user->setEmail('test@example.com');
$manager->persist($user);
$manager->flush();
}
ApiTestCase for API-specific assertions (e.g., status codes, JSON responses).
$this->assertJson($response->getContent());
$this->assertArrayHasKey('data', json_decode($response->getContent(), true));
Request/Response Testing
get(), post(), put(), delete() with optional payloads:
$response = $this->postJson('/api/users', ['name' => 'John']);
$this->assertEquals(201, $response->getStatusCode());
withServerParameters():
$this->withServerParameters(['HTTP_Authorization' => 'Bearer token']);
Database Isolation
$this->beginTransaction();
// Test logic
$this->rollBack();
Scenario Testing
$response = $this->postJson('/api/orders', ['product_id' => 1]);
$orderId = json_decode($response->getContent(), true)['id'];
$this->assertDatabaseHas('orders', ['id' => $orderId]);
Database Reset Timing
$this->beginTransaction();
try {
// Test logic
$this->commit();
} catch (\Exception $e) {
$this->rollBack();
throw $e;
}
Fixture Loading Order
UserFixtures, OrderFixtures where UserFixtures depends on User).Environment Configuration
.env.test is used for tests (not .env). Override database settings:
# .env.test
DATABASE_URL="sqlite:///%kernel.project_dir%/var/test.db"
CORS/Headers in Tests
$this->withServerParameters([
'HTTP_ORIGIN' => 'http://example.com',
'CONTENT_TYPE' => 'application/json',
]);
phpunit.xml:
<php>
<env name="APP_ENV" value="test"/>
<env name="APP_DEBUG" value="1"/>
</php>
config/packages/dev/doctrine.yaml:
doctrine:
dbal:
logging: true
profiling: true
file_put_contents('debug_response.json', $response->getContent());
Custom Assertions
Extend ApiTestCase to add reusable assertions:
protected function assertApiSuccess($response)
{
$this->assertEquals(200, $response->getStatusCode());
$this->assertJson($response->getContent());
}
Mocking Services
Use Symfony’s createMock() or MockBuilder for external services:
$paymentGateway = $this->createMock(PaymentGateway::class);
$paymentGateway->method('charge')->willReturn(true);
$this->container->set(PaymentGateway::class, $paymentGateway);
Parallel Testing Configure PHPUnit for parallel runs (requires SQLite for isolation):
<phpunit>
<extensions>
<extension class="Parallel\Extension"/>
</extensions>
</phpunit>
How can I help you explore Laravel packages today?