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; } }