Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
<?php
namespace MyTestNamespace;
//relevant use clauses
use ...
final class AddItemIntegrationTest extends \PHPUnit_Framework_TestCase
{
public function testAddItem()
{
$orderId = OrderId::new() // generates a new OrderId value object
$item = ItemId::new(); // generates a new ItemId value object
$command = AddItem::fromOrderItemAndQuantity(
$orderId,
$item,
7
);
$container = $this->buildContainer();
// override database Connection
$container->setFactory(
Connection::class,
function (ContainerInterface $container) use ($orderId, $item) {
$connection = \Mockery::mock(Connection::class);
// framework initial calls
$connection->shouldReceive('getTransactionNestingLevel')->andReturn(0);
$connection->shouldReceive('beginTransaction');
// retrieve events from the event store
$queryBuilder = Mockery::mock(QueryBuilder::class.['execute'], [$connection]);
$statement = Mockery::mock(Statement::class);
$statement->shouldReceive('setFetchMode');
$customer = CustomerId::new(); // generates a new CustomerId value object
$statement->shouldReceive('fetch')->once()->andReturn([
'event_name' => OrderWasCreated::class,
'event_id' => Uuid::uuid4(),
'aggregate_id' => (string) $orderId,
'payload' => json_encode([
'customer' => (string) $customer
]),
'created_at' => date_create()->format('Y-m-d\\TH:i:s.u'),
'version' => 1
]);
$statement->shouldReceive('fetch')->andReturn(false);
$queryBuilder->shouldReceive('execute')->andReturn($statement);
$connection->shouldReceive('createQueryBuilder')->andReturn($queryBuilder);
// check conditions on the read model
$connection->shouldReceive('fetchColumn')->with(
'SELECT availability FROM item_availability WHERE id = :id',
['id' => (string) $item]
)->andReturn(10);
// persist events in the event store
$connection->shouldReceive('insert')->with(
'event_stream',
\Mockery::on(function (array $record) use ($orderId, $item) {
return $record['event_name'] === ItemWasAdded::class &&
$record['aggregate_id'] === (string) $orderId &&
$record['aggregate_name'] === Order::class &&
$record['payload'] === json_encode([
'item' => (string) $item,
'quantity' => 7
]) &&
$record['causation_name'] === AddItem::class &&
$record['version'] === 2;
})
);
// retrieve data needed to update the read side
// RETRIEVE THE CUSTOMER DATA
$connection->shouldReceive('fetchAssoc')->with(
'SELECT customer_id, customer_name, customer_email '.
'FROM orders WHERE id = :id',
['id' => (string) $orderId]
)->andReturn([
'customer_id' => (string) $customer,
'customer_name' => 'marco perone',
'customer_email' => 'marco@perone.com'
]);
// RETRIEVE THE ITEM DATA
$connection->shouldReceive('fetchAssoc')->with(
'SELECT name, price, currency FROM items WHERE id = :id',
['id' => (string) $item]
)->andReturn([
'name' => 'item name',
'price' => 156,
'currency' => 'EUR'
]);
// update the read side
$connection->shouldReceive('insert')->with('order_items', [
'order_id' => (string) $orderId,
'customer_id' => (string) $customer,
'customer_name' => 'marco perone',
'customer_email' => 'email@domain.com',
'item_id' => (string) $item,
'item_name' => 'item name',
'item_price' => 156,
'item_currency' => 'EUR',
'quantity' => 7
]);
return $connection;
}
);
$commandBus = (new CommandBusFactory())($container);
$commandBus($command);
}
private buildContainer()
{
// retrieve configuration
$config = [];
$files = Glob::glob(
'config/autoload/{{,*.}global,{,*.}local}.php',
Glob::GLOB_BRACE
);
foreach ($files as $file) {
$config = ArrayUtils::merge($config, include $file);
}
$container = new ServiceManager();
(new Config($config['service_manager']))->configureServiceManager($container);
// Inject config
$container->setService('config', $config);
return $container;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment