Test your application
Introductionβ
BowPHP's functional testing API lets you test your APIs fluently using HTTP requests. This API is built around PHPUnit, which means you can leverage the full power of that framework to run your tests. The main HTTP operations (GET, POST, PUT, DELETE, PATCH) are covered, and you can add headers or attachments to your requests.
The TestCase classβ
The main class for using the testing API is TestCase, which extends PHPUnit's PHPUnitTestCase class. It provides a simple interface for sending HTTP requests and verifying responses.
Methods of the TestCase classβ
The base URL for HTTP calls is resolved, in this order:
- The test's
protected ?string $urlproperty (if set). - The
APP_URLenvironment variable. - The
http://127.0.0.1:8080fallback (the default port ofphp bow run:server).
To customize the resolution, override the protected
getBaseUrl(): string method in your test class.
1. attach(array $attach)β
Adds multipart files / fields to the next request. Attachments are consumed after the call and do not leak into subsequent requests within the same test.
$test->attach([
'file' => new \CURLFile('/path/to/file.jpg')
])->post('/upload');
2. withHeaders(array $headers)β
Replaces the headers applied to all subsequent requests in the test.
$test->withHeaders([
'Authorization' => 'Bearer token',
'Content-Type' => 'application/json',
]);
3. withHeader(string $key, string $value)β
Adds (or replaces) a single header.
$test->withHeader('X-Custom-Header', 'custom_value');
4. get(string $url, array $param = [])β
GET request. Parameters are appended to the query string.
$response = $test->get('/api/users', ['page' => 1]);
5. post(string $url, array $param = [])β
POST request. Combine with attach() to send files.
$response = $test->post('/api/users', ['name' => 'John Doe']);
6. put(string $url, array $param = [])β
PUT request.
$response = $test->put('/api/users/1', ['name' => 'John Updated']);
7. delete(string $url, array $param = [])β
A real HTTP DELETE request (no more _method POST hack).
$response = $test->delete('/api/users/1');
8. patch(string $url, array $param = [])β
A real HTTP PATCH request.
$response = $test->patch('/api/users/1', ['name' => 'John Modified']);
9. head(string $url, array $param = [])β
HEAD request: retrieves only the headers, without a body. Useful for checking the existence of a resource or its metadata.
$response = $test->head('/api/users/1');
$response->assertStatus(200);
10. options(string $url)β
OPTIONS request β typically used for CORS preflight.
$response = $test->options('/api/users');
11. visit(string $method, string $url, array $params = [])β
A generic dispatcher based on the HTTP verb. Accepts
get, post, put, patch, delete, head, options.
$response = $test->visit('patch', '/api/users/1', ['name' => 'X']);
Complete usage exampleβ
Here is a complete example showing how to set up a functional test with the testing API:
use Bow\Testing\TestCase;
class UserApiTest extends TestCase
{
protected ?string $url = 'http://localhost:8080';
public function testCreateUser()
{
// Add an authorization header
$this->withHeader('Authorization', 'Bearer token');
// Add test data to send in the POST request
$data = [
'name' => 'John Doe',
'email' => '[email protected]'
];
// Perform the POST request
$response = $this->post('/api/users', $data);
// Verify that the response has HTTP status 201
$response->assertStatus(201);
$result = $response->toArray();
// Verify that the name of the created user is correct
$this->assertEquals('John Doe', $result['name']);
}
public function testGetUser()
{
// Make a GET request to retrieve a user
$response = $this->get('/api/users/1');
// Verify that the response has HTTP status 200
$response->assertStatus(200);
$result = $response->toArray();
// Verify that the user ID is correct
$this->assertEquals(1, $result['id']);
}
}
The Response class for functional testsβ
The Response class lets you manipulate HTTP responses in the context of functional tests with BowPHP. It wraps an object of the HttpClientResponse class and exposes several methods for making assertions about the response.
Methods of the Response classβ
1. assertJson(string $message = ''): Responseβ
Verifies that the response content is in JSON format. If it is not, a test failure will be raised.
$response->assertJson("The response should be in JSON format");
2. assertExactJson(array $data, string $message = ''): Responseβ
Verifies that the JSON content of the response exactly matches the specified data.
$response->assertExactJson([
'name' => 'John Doe',
'email' => '[email protected]'
], "The JSON response does not match the expected data.");
3. assertContainsExactText(string $data, string $message = ''): Responseβ
Verifies that the response content exactly matches the given text.
$response->assertContainsExactText("Welcome, John Doe", "The response text does not match.");
4. assertHeader(string $header, string $message = ''): Responseβ
Verifies that a specific header exists in the response.
$response->assertHeader('Content-Type', "The Content-Type header is missing.");
5. assertArray(string $message = ''): Responseβ
Verifies that the response content is an array.
$response->assertArray("The response should be an array.");
6. assertContentType(string $content_type, string $message = ''): Responseβ
Verifies that the response content type matches the one specified.
$response->assertContentType('application/json', "The content type is not 'application/json'.");
7. assertContentTypeJson(string $message = ''): Responseβ
Verifies that the content type is application/json.
$response->assertContentTypeJson("The content type should be JSON.");
8. assertContentTypeText(string $message = ''): Responseβ
Verifies that the content type is text/plain.
$response->assertContentTypeText("The content type should be text/plain.");
9. assertContentTypeHtml(string $message = ''): Responseβ
Verifies that the content type is text/html.
$response->assertContentTypeHtml("The content type should be text/html.");
10. assertContentTypeXml(string $message = ''): Responseβ
Verifies that the content type is text/xml.
$response->assertContentTypeXml("The content type should be text/xml.");
11. assertStatus(int $code, string $message = ''): Responseβ
Verifies that the HTTP status code of the response matches the one specified.
$response->assertStatus(200, "The HTTP status is not 200.");
12. assertKeyExists(string $key, string $message = ''): Responseβ
Verifies that a key exists in the JSON content of the response.
$response->assertKeyExists('id', "The 'id' key is missing in the response.");
13. assertKeyMatchValue(string|int $key, mixed $value, string $message = ''): Responseβ
Verifies that a specific key in the JSON content of the response matches a specified value.
$response->assertKeyMatchValue('name', 'John Doe', "The name in the response does not match.");
14. assertContains(string $text): Responseβ
Verifies that the response content contains a specific substring.
$response->assertContains("Welcome", "The text 'Welcome' should be present.");
15. getContent(): stringβ
Retrieves the raw content of the response.
$content = $response->getContent();
16. toArray(): array|objectβ
Returns the response content as an array or object (if the content is JSON).
$data = $response->toArray();
17. __call(string $method, array $params = [])β
Allows dynamic calls to the methods of the HttpClientResponse object wrapped in the response.
$response->getCode(); // Calls getCode() on HttpClientResponse
Complete usage exampleβ
Here is a complete example showing how to use the Response class to test an API:
use Bow\Testing\TestCase;
class UserApiTest extends TestCase
{
public function testCreateUser()
{
// Perform a POST request
$data = [
'name' => 'John Doe',
'email' => '[email protected]'
];
$response = $this->post('/api/users', $data);
// Verify that the response has status 201
$response->assertStatus(201, "The HTTP status should be 201");
// Verify that the content is JSON
$response->assertJson("The response should be JSON");
// Verify that the name in the response is correct
$response->assertKeyMatchValue('name', 'John Doe', "The user name is incorrect.");
}
public function testGetUser()
{
// Perform a GET request
$response = $this->get('/api/users/1');
// Verify that the response has status 200
$response->assertStatus(200, "The HTTP status should be 200");
// Verify that the user exists
$response->assertKeyExists('id', "The user ID should exist.");
}
}
Referencesβ
See the official PHPUnit documentation for more information about assertions and advanced features.
Is something missing?
If you run into problems with the documentation or have suggestions to improve the documentation or the project in general, please open an issue for us, or send a tweet mentioning the Twitter account @bowframework or directly on github.