Test Code Reuse
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeWe'll have a bunch of test classes and they'll all need to create a Guzzle Client
with these options. So let's just get organized now.
Create a new Test
directory in the bundle and a new class called ApiTestCase
. This will be a base class for all our API tests. Make it extend the normal PHPUnit_Framework_TestCase
:
// ... lines 1 - 2 | |
namespace AppBundle\Test; | |
// ... lines 4 - 6 | |
class ApiTestCase extends \PHPUnit_Framework_TestCase | |
{ | |
// ... lines 9 - 29 | |
} |
Right now, the thing I want to move out of each test class is the creation of the Guzzle Client
. So copy that code. In ApiTestCase
, override a method called setupBeforeClass()
- it's static. PHPUnit calls this one time at the beginning of running your whole test suite.
Paste the $client
code here. Because really, even if we run A LOT of tests, we can probably always use the same Guzzle client. Create a private static
property called $staticClient
and put the Client
there with self::$staticClient
. And give Client
a proper use
statement:
// ... lines 1 - 6 | |
class ApiTestCase extends \PHPUnit_Framework_TestCase | |
{ | |
private static $staticClient; | |
// ... lines 10 - 15 | |
public static function setUpBeforeClass() | |
{ | |
self::$staticClient = new Client([ | |
'base_url' => 'http://localhost:8000', | |
'defaults' => [ | |
'exceptions' => false | |
] | |
]); | |
} | |
// ... lines 25 - 29 | |
} |
Tip
In case you are using Guzzle 6, you would need to use the base_uri
key instead of base_url
to configure Guzzle client properly.
Cool. So now the Client
is created once per test suite. Now, create a protected $client
property that is not static with some nice PHPDoc above it. Woops - make sure you actually make this protected
: this is what we'll use in the sub-classes. Then, override setup()
and say $this->client = self::$staticClient
:
// ... lines 1 - 6 | |
class ApiTestCase extends \PHPUnit_Framework_TestCase | |
{ | |
// ... lines 9 - 10 | |
/** | |
* @var Client | |
*/ | |
protected $client; | |
// ... lines 15 - 25 | |
protected function setUp() | |
{ | |
$this->client = self::$staticClient; | |
} | |
} |
setupBeforeClass()
will make sure the Client
is created just once and setup()
puts that onto a non-static property, just because I like non-static things a bit better. Oh, and if we did need to do any clean up resetting of the Client, we could do that in setup()
or tearDown()
.
Extend the Base Class
Back in the actual test class, get rid of the $client
code and simply reference $this->client
. Ooooo, and don't forget to extend ApiTestCase
like I just did:
// ... lines 1 - 3 | |
use AppBundle\Test\ApiTestCase; | |
class ProgrammerControllerTest extends ApiTestCase | |
{ | |
public function testPOST() | |
{ | |
// ... lines 10 - 16 | |
// 1) Create a programmer resource | |
$response = $this->client->post('/api/programmers', [ | |
'body' => json_encode($data) | |
]); | |
// ... lines 21 - 25 | |
} | |
} |
Make sure we didn't break anything:
php bin/phpunit -c app src/AppBundle/Tests/Controller/Api/ProgrammerControllerTest.php
Hey, still green!
APITestCase for Symfony4 seems to break. I'm getting user not found. It seems to be still hitting my app database instead of app_test database.