1. Go to this page and download the library: Download tobento/app-testing library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
tobento / app-testing example snippets
use Tobento\App\Testing\TestCase;
use Tobento\App\AppInterface;
final class SomeAppTest extends TestCase
{
public function createApp(): AppInterface
{
return
use Tobento\App\Testing\TestCase;
use Tobento\App\AppInterface;
final class SomeAppTest extends TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(SomeRoutes::class);
// ...
return $app;
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'foo/bar');
// interact with the app:
$app = $this->getApp();
$app->booting();
$app->run();
// or
$app = $this->bootingApp();
$app->run();
// or
$app = $this->runApp();
// assertions:
$http->response()
->assertStatus(200)
->assertBodySame('foo');
}
}
final class SomeAppTest extends TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(SomeRoutes::class);
// ...
return $app;
}
public function testSomeRoute(): void
{
// testing...
$this->deleteAppDirectory();
}
}
final class SomeAppTest extends TestCase
{
protected function tearDown(): void
{
parent::tearDown();
$this->deleteAppDirectory();
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomething(): void
{
// faking:
$config = $this->fakeConfig();
$config->with('app.environment', 'testing');
$this->runApp();
// assertions:
$config
->assertExists(key: 'app.environment')
->assertSame(key: 'app.environment', value: 'testing');
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/1');
// you may interact with the app:
$app = $this->getApp();
$app->booting();
// assertions:
$http->response()
->assertStatus(200)
->assertBodySame('foo');
}
}
use Psr\Http\Message\ResponseInterface;
$http->response()
->assertStatus(200)
->assertBodySame('foo')
->assertBodyNotSame('bar')
->assertBodyContains('foo')
->assertBodyNotContains('bar')
->assertContentType('application/json')
->assertHasHeader(name: 'Content-type')
->assertHasHeader(name: 'Content-type', value: 'application/json') // with value
->assertHeaderMissing(name: 'Content-type')
->assertCookieExists(key: 'token')
->assertCookieMissed(key: 'token')
->assertCookieSame(key: 'token', value: 'value')
->assertHasSession(key: 'key')
->assertHasSession(key: 'key', value: 'value') // with value
->assertSessionMissing(key: 'key')
->assertLocation(uri: 'uri')
->assertRedirectToRoute(name: 'route', parameters: []);
// you may get the response:
$response = $http->response()->response();
var_dump($response instanceof ResponseInterface::class);
// bool(true)
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->withoutMiddleware(Middleware::class, AnotherMiddleware::class);
$http->request('GET', 'user/1');
// assertions:
$http->response()->assertStatus(200);
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->previousUri('users/create');
$http->request('POST', 'users');
// Or after booting using a named route:
$app = $this->bootingApp();
$http->previousUri($app->routeUrl('users.create'));
// assertions:
$http->response()
->assertStatus(301)
->assertLocation(uri: 'users/create');
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$config = $this->fakeConfig();
$config->with('http.url', ''); // modify
$http = $this->fakeHttp();
$http->request('GET', 'orders');
// assertions:
$http->response()
// if modified:
->assertNodeExists('a[href="orders/5"]')
// if not modified:
->assertNodeExists('a[href="http://localhost/orders/5"]');
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/1');
// assertions:
$http->response()->assertStatus(200);
// subsequent request:
$http->request('GET', 'user/2');
// assertions:
$http->response()->assertStatus(200);
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'login');
$auth = $this->fakeAuth();
// you may interact with the app:
$app = $this->bootingApp();
$user = $auth->getUserRepository()->create(['username' => 'tom']);
$auth->authenticatedAs($user);
// assertions:
$http->response()->assertStatus(302);
$auth->assertAuthenticated();
// following redirects:
$http->followRedirects()->assertStatus(200);
// fakers others than http, must be recalled.
$this->fakeAuth()->assertAuthenticated();
// $auth->assertAuthenticated(); // would be from previous request
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request(
method: 'GET',
uri: 'user/1',
files: [
// Create a fake image 640x480
'profile' => $http->getFileFactory()->createImage('profile.jpg', 640, 480),
],
);
// assertions:
$http->response()->assertStatus(200);
}
}
use Tobento\App\Testing\TestCase;
use Symfony\Component\DomCrawler\Crawler;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/comments');
// assertions:
$response = $http->response()->assertStatus(200);
$this->assertCount(4, $response->crawl()->filter('.comment'));
// returns the crawler:
$crawler = $response()->crawl(); // Crawler
}
}
use Tobento\App\Testing\TestCase;
use Symfony\Component\DomCrawler\Crawler;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/comments');
// assertions:
$http->response()
->assertStatus(200)
// Assert if a node exists:
->assertNodeExists('a[href="https://example.com"]')
// Assert if a node exists based on a truth-test callback:
->assertNodeExists('h1', fn (Crawler $n): bool => $n->text() === 'Comments')
// Assert if a node exists based on a truth-test callback:
->assertNodeExists('ul', static function (Crawler $n) {
return $n->children()->count() === 2
&& $n->children()->first()->text() === 'foo';
}, 'There first ul child has no text "foo"');
}
}
use Tobento\App\Testing\TestCase;
use Symfony\Component\DomCrawler\Crawler;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/comments');
// assertions:
$http->response()
->assertStatus(200)
// Assert if a node is missing:
->assertNodeMissing('h1')
// Assert if a node is missing based on a truth-test callback:
->assertNodeMissing('p', static function (Crawler $n) {
return $n->attr('class') === 'error'
&& $n->text() === 'Error Message';
}, 'An unexpected error message was found');
}
}
use Tobento\App\Testing\TestCase;
use Symfony\Component\DomCrawler\Crawler;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/comments');
// assertions:
$response = $http->response()->assertStatus(200);
$form = $response->crawl(
// you may pass a base uri or base href:
uri: 'http://www.example.com',
baseHref: null,
)->selectButton('My super button')->form();
$this->assertSame('POST', $form->getMethod());
}
}
use Tobento\App\Testing\TestCase;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'api/user/1');
// assertions:
$http->response()
->assertStatus(200)
->assertJson([
'id' => 1,
'name' => 'John',
]);
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\Testing\Http\AssertableJson;
final class SomeAppTest extends TestCase
{
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'api/users');
// assertions:
$http->response()
->assertJson(fn (AssertableJson $json) =>
$json->has(items: 3)
->has(key: '0', items: 2, value: AssertableJson $json) =>
$json->has(key: 'id', value: 1)
->has(key: 'name', value: 'Tom')
)
);
}
}
$json->has(key: 'name');
// using dot notation:
$json->has(key: 'address.firstname');
use Tobento\App\Testing\Http\TestResponse;
final class SomeAppTest extends TestCase
{
public function createApp(): AppInterface
{
// ...
// we may add the macro here:
TestResponse::macro('assertOk', function(): static {
$this->assertStatus(200);
return $this;
});
return $app;
}
public function testSomeRoute(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'user/comments');
// assertions:
$http->response()->assertOk();
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\Testing\Http\RefreshSession;
final class SomeAppTest extends TestCase
{
use RefreshSession;
public function testSomething(): void
{
// ...
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\User\UserRepositoryInterface;
final class SomeAppTest extends TestCase
{
public function testSomeRouteWhileAuthenticated(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'profile');
$auth = $this->fakeAuth();
// you may change the token storage:
//$auth->tokenStorage('inmemory');
//$auth->tokenStorage('session');
//$auth->tokenStorage('repository');
// boot the app:
$app = $this->bootingApp();
// authenticate user:
$userRepo = $app->get(UserRepositoryInterface::class);
$user = $userRepo->findByIdentity(email: '[email protected]');
// or:
$user = $auth->getUserRepository()->findByIdentity(email: '[email protected]');
$auth->authenticatedAs($user);
// assertions:
$http->response()->assertStatus(200);
$auth->assertAuthenticated();
// or:
//$auth->assertNotAuthenticated();
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\User\UserRepositoryInterface;
final class SomeAppTest extends TestCase
{
public function testSomeRouteWhileAuthenticated(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'profile');
$auth = $this->fakeAuth();
// boot the app:
$app = $this->bootingApp();
// authenticate user:
$user = $auth->getUserRepository()->findByIdentity(email: '[email protected]');
$token = $auth->getTokenStorage()->createToken(
payload: ['userId' => $user->id(), 'passwordHash' => $user->password()],
authenticatedVia: 'loginform',
authenticatedBy: 'testing',
//issuedAt: $issuedAt,
//expiresAt: $expiresAt,
);
$auth->authenticatedAs($token);
// assertions:
$http->response()->assertStatus(200);
$auth->assertAuthenticated();
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\Testing\Database\RefreshDatabases;
use Tobento\App\User\UserRepositoryInterface;
use Tobento\App\User\AddressRepositoryInterface;
use Tobento\App\Seeding\User\UserFactory;
final class SomeAppTest extends TestCase
{
use RefreshDatabases;
public function testSomeRouteWhileAuthenticated(): void
{
// faking:
$http = $this->fakeHttp();
$http->request('GET', 'profile');
$auth = $this->fakeAuth();
// boot the app:
$app = $this->bootingApp();
// Create a user:
$user = $auth->getUserRepository()->create(['username' => 'tom']);
// or using the user factory:
$user = UserFactory::new()->withUsername('tom')->withPassword('123456')->createOne();
// authenticate user:
$auth->authenticatedAs($user);
// assertions:
$http->response()->assertStatus(200);
$auth->assertAuthenticated();
}
}
use Psr\Http\Message\ServerRequestInterface;
use Tobento\App\AppInterface;
use Tobento\App\Testing\FileStorage\RefreshFileStorages;
use Tobento\Service\FileStorage\StoragesInterface;
use Tobento\Service\FileStorage\Visibility;
use Tobento\Service\Routing\RouterInterface;
class FileStorageTest extends \Tobento\App\Testing\TestCase
{
// you may refresh all file storages after each test.
use RefreshFileStorages;
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(\Tobento\App\FileStorage\Boot\FileStorage::class);
// routes: just for demo, normally done with a boot!
$app->on(RouterInterface::class, static function(RouterInterface $router): void {
$router->post('upload', function (ServerRequestInterface $request, StoragesInterface $storages) {
$file = $request->getUploadedFiles()['profile'];
$storage = $storages->get('uploads');
$storage->write(
path: $file->getClientFilename(),
content: $file->getStream()
);
$storage->copy(from: $file->getClientFilename(), to: 'copy/'.$file->getClientFilename());
$storage->move(from: 'copy/'.$file->getClientFilename(), to: 'move/'.$file->getClientFilename());
$storage->createFolder('foo/bar');
$storage->setVisibility('foo/bar', Visibility::PRIVATE);
return 'response';
});
});
return $app;
}
public function testFileUpload()
{
// fakes:
$fileStorage = $this->fakeFileStorage();
$http = $this->fakeHttp();
$http->request(
method: 'POST',
uri: 'upload',
files: [
// Create a fake image 640x480
'profile' => $http->getFileFactory()->createImage('profile.jpg', 640, 480),
],
);
// run the app:
$this->runApp();
// assertions:
$fileStorage->storage(name: 'uploads')
->assertCreated('profile.jpg')
->assertNotCreated('foo.jpg')
->assertExists('profile.jpg')
->assertNotExist('foo.jpg')
->assertCopied(from: 'profile.jpg', to: 'copy/profile.jpg')
->assertNotCopied(from: 'foo.jpg', to: 'copy/foo.jpg')
->assertMoved(from: 'copy/profile.jpg', to: 'move/profile.jpg')
->assertNotMoved(from: 'foo.jpg', to: 'copy/foo.jpg')
->assertFolderCreated('foo/bar')
->assertFolderNotCreated('baz')
->assertFolderExists('foo/bar')
->assertFolderNotExist('baz')
->assertVisibilityChanged('foo/bar');
}
}
$fileStorage = $this->fakeFileStorage();
// Get default storage:
$defaultStorage = $fileStorage->storage();
// Get specific storage:
$storage = $fileStorage->storage(name: 'uploads');
use Tobento\Service\FileStorage\StoragesInterface;
$fileStorage = $this->fakeFileStorage();
// Get the storages:
$storages = $fileStorage->storages();
var_dump($storages instanceof StoragesInterface);
// bool(true)
use Tobento\App\AppInterface;
use Tobento\Service\Routing\RouterInterface;
use Psr\Http\Message\ServerRequestInterface;
use Tobento\Service\Queue\QueueInterface;
use Tobento\Service\Queue\JobInterface;
use Tobento\Service\Queue\Job;
class QueueTest extends \Tobento\App\Testing\TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(\Tobento\App\Queue\Boot\Queue::class);
// routes: just for demo, normally done with a boot!
$app->on(RouterInterface::class, static function(RouterInterface $router): void {
$router->post('queue', function (ServerRequestInterface $request, QueueInterface $queue) {
$queue->push(new Job(
name: 'sample',
payload: ['key' => 'value'],
));
return 'response';
});
});
return $app;
}
public function testIsQueued()
{
// fakes:
$fakeQueue = $this->fakeQueue();
$http = $this->fakeHttp();
$http->request(method: 'POST', uri: 'queue');
// run the app:
$this->runApp();
// assertions:
$fakeQueue->queue(name: 'sync')
->assertPushed('sample')
->assertPushed('sample', function (JobInterface $job): bool {
return $job->getPayload()['key'] === 'value';
})
->assertNotPushed('sample:foo')
->assertNotPushed('sample', function (JobInterface $job): bool {
return $job->getPayload()['key'] === 'invalid';
})
->assertPushedTimes('sample', 1);
$fakeQueue->queue(name: 'file')
->assertNothingPushed();
}
}
use Tobento\Service\Queue\QueueInterface;
$fakeQueue->clearQueue(
queue: $fakeQueue->queue(name: 'file') // QueueInterface
);
use Tobento\App\AppInterface;
use Tobento\Service\Routing\RouterInterface;
use Tobento\Service\Event\EventsInterface;
use Psr\Http\Message\ServerRequestInterface;
class QueueTest extends \Tobento\App\Testing\TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(\Tobento\App\Event\Boot\Event::class);
// routes: just for demo, normally done with a boot!
$app->on(RouterInterface::class, static function(RouterInterface $router): void {
$router->post('registration', function (ServerRequestInterface $request, EventsInterface $events) {
$events->dispatch(new UserRegistered(username: 'tom'));
return 'response';
});
});
return $app;
}
public function testDispatchesEvent()
{
// fakes:
$events = $this->fakeEvents();
$http = $this->fakeHttp();
$http->request(method: 'POST', uri: 'registration');
// run the app:
$this->runApp();
// assertions:
$events
// Assert if an event dispatched one or more times:
->assertDispatched(UserRegistered::class)
// Assert if an event dispatched one or more times based on a truth-test callback:
->assertDispatched(UserRegistered::class, static function(UserRegistered $event): bool {
return $event->username === 'tom';
})
// Asserting if an event were dispatched a specific number of times:
->assertDispatchedTimes(UserRegistered::class, 1)
// Asserting an event were not dispatched:
->assertNotDispatched(FooEvent::class)
// Asserting an event were not dispatched based on a truth-test callback:
->assertNotDispatched(UserRegistered::class, static function(UserRegistered $event): bool {
return $event->username !== 'tom';
})
// Assert if an event has a listener attached to it:
->assertListening(UserRegistered::class, SomeListener::class);
}
}
use Tobento\App\AppInterface;
use Tobento\Service\Routing\RouterInterface;
use Psr\Http\Message\ServerRequestInterface;
use Tobento\Service\Mail\MailerInterface;
use Tobento\Service\Mail\Message;
use Tobento\Service\Mail\Address;
use Tobento\Service\Mail\Parameter;
class MailTest extends \Tobento\App\Testing\TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(\Tobento\App\View\Boot\View::class); // to support message templates
$app->boot(\Tobento\App\Mail\Boot\Mail::class);
// routes: just for demo, normally done with a boot!
$this->getApp()->on(RouterInterface::class, static function(RouterInterface $router): void {
$router->post('mail', function (ServerRequestInterface $request, MailerInterface $mailer) {
$message = (new Message())
->from('[email protected]')
->to(new Address('[email protected]', 'Name'))
->subject('Subject')
->html('<p>Lorem Ipsum</p>');
$mailer->send($message);
return 'response';
});
});
return $app;
}
public function testMessageMailed()
{
// fakes:
$fakeMail = $this->fakeMail();
$http = $this->fakeHttp();
$http->request(method: 'POST', uri: 'mail');
// run the app:
$this->runApp();
// assertions:
$fakeMail->mailer(name: 'default')
->sent(Message::class)
->assertFrom('[email protected]', 'Name')
->assertHasTo('[email protected]', 'Name')
->assertHasCc('[email protected]', 'Name')
->assertHasBcc('[email protected]', 'Name')
->assertReplyTo('[email protected]', 'Name')
->assertSubject('Subject')
->assertTextContains('Lorem')
->assertHtmlContains('Lorem')
->assertIsQueued()
->assertHasParameter(
Parameter\File::class,
fn (Parameter\File $f) => $f->file()->getBasename() === 'image.jpg'
)
->assertTimes(1);
}
}
use Tobento\App\AppInterface;
use Tobento\Service\Routing\RouterInterface;
use Psr\Http\Message\ServerRequestInterface;
use Tobento\Service\Notifier\NotifierInterface;
use Tobento\Service\Notifier\ChannelMessagesInterface;
use Tobento\Service\Notifier\Notification;
use Tobento\Service\Notifier\Recipient;
class NotifierTest extends \Tobento\App\Testing\TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(\Tobento\App\Notifier\Boot\Notifier::class);
// routes: just for demo, normally done with a boot!
$this->getApp()->on(RouterInterface::class, static function(RouterInterface $router): void {
$router->post('notify', function (ServerRequestInterface $request, NotifierInterface $notifier) {
$notification = new Notification(
subject: 'New Invoice',
content: 'You got a new invoice for 15 EUR.',
channels: ['mail', 'sms', 'storage'],
);
// The receiver of the notification:
$recipient = new Recipient(
email: '[email protected]',
phone: '15556666666',
id: 5,
);
$notifier->send($notification, $recipient);
return 'response';
});
});
return $app;
}
public function testNotified()
{
// fakes:
$notifier = $this->fakeNotifier();
$http = $this->fakeHttp();
$http->request(method: 'POST', uri: 'notify');
// run the app:
$this->runApp();
// assertions:
$notifier
// Assert if a notification is sent one or more times:
->assertSent(Notification::class)
// Assert if a notification is sent one or more times based on a truth-test callback:
->assertSent(Notification::class, static function(ChannelMessagesInterface $messages): bool {
$notification = $messages->notification();
$recipient = $messages->recipient();
// you may test the sent messages
$mail = $messages->get('mail')->message();
$this->assertSame('New Invoice', $mail->getSubject());
return $notification->getSubject() === 'New Invoice'
&& $messages->successful()->channelNames() === ['mail', 'sms', 'storage']
&& $messages->get('sms')->message()->getTo()->phone() === '15556666666'
&& $recipient->getAddressForChannel('mail', $notification)?->email() === '[email protected]';
})
// Asserting if a notification were sent a specific number of times:
->assertSentTimes(Notification::class, 1)
// Asserting a notification were not sent:
->assertNotSent(Notification::class)
// Asserting a notification were not sent based on a truth-test callback:
->assertNotSent(Notification::class, static function(ChannelMessagesInterface $messages): bool {
$notification = $messages->notification();
return $notification->getSubject() === 'New Invoice';
})
// Asserting that no notifications were sent:
->assertNothingSent();
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\Testing\Database\RefreshDatabases;
final class SomeAppTest extends TestCase
{
use RefreshDatabases;
public function testSomething(): void
{
// ...
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\Testing\Database\MigrateDatabases;
final class SomeAppTest extends TestCase
{
use MigrateDatabases;
public function testSomething(): void
{
// ...
}
}
use Tobento\App\Testing\TestCase;
use Tobento\App\AppInterface;
use Tobento\App\Testing\Database\RefreshDatabases;
use Tobento\Service\Database\DatabasesInterface;
use Tobento\Service\Database\DatabaseInterface;
use Tobento\Service\Database\PdoDatabase;
final class SomeAppTest extends TestCase
{
use RefreshDatabases;
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..', folder: 'app-mysql');
$app->boot(\Tobento\App\User\Boot\User::class);
// example changing databases:
$app->on(DatabasesInterface::class, static function (DatabasesInterface $databases) {
// change default storage database:
$databases->addDefault('storage', 'mysql-storage');
// you may change the mysql database:
$databases->register(
'mysql',
function(string $name): DatabaseInterface {
return new PdoDatabase(
new \PDO(
dsn: 'mysql:host=localhost;dbname=app_testing',
username: 'root',
password: '',
),
$name
);
}
);
});
return $app;
}
public function testSomething(): void
{
// ...
}
}
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use Tobento\App\AppInterface;
use Tobento\App\Testing\Logging\LogEntry;
use Tobento\Service\Routing\RouterInterface;
class LoggingTest extends \Tobento\App\Testing\TestCase
{
public function createApp(): AppInterface
{
$app = $this->createTmpApp(rootDir: __DIR__.'/..');
$app->boot(\Tobento\App\Http\Boot\Routing::class);
$app->boot(\Tobento\App\Logging\Boot\Logging::class);
// routes: just for demo, normally done with a boot!
$app->on(RouterInterface::class, static function(RouterInterface $router): void {
$router->post('login', function (ServerRequestInterface $request, LoggerInterface $logger) {
$logger->info('User logged in.', ['user_id' => 3]);
return 'response';
});
});
return $app;
}
public function testIsLogged()
{
// fakes:
$fakeLogging = $this->fakeLogging();
$http = $this->fakeHttp();
$http->request(method: 'POST', uri: 'login');
// run the app:
$this->runApp();
// assertions using default logger:
$fakeLogging->logger()
->assertLogged(fn (LogEntry $log): bool =>
$log->level === 'info'
&& $log->message === 'User logged in.'
&& $log->context === ['user_id' => 3]
)
->assertNotLogged(
fn (LogEntry $log): bool => $log->level === 'error'
)
->assertLoggedTimes(
fn (LogEntry $log): bool => $log->level === 'info',
1
);
// specific logger:
$fakeLogging->logger(name: 'error')
->assertNothingLogged();
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.