Test API output format using Open API Spec 3 document.
1.x
: Supports PHP 7.2.2.x
: Supports PHP 7.4 and above.
Install this package into your project:
composer require goez/open-api-tester --dev
Generate an API documentation example and a PHPUnit test case in your Laravel project:
php artisan vendor:publish --tag=open-api-tester
The command will generate the following files:
docs/api/*
: The API documentation example.tests/Feature/OpenApiSchemaTest.php
: The PHPUnit test case.
In the operation level of the document, add an x-api-tests
extended field. Inside it, list one or more test cases in an array format.
The format of a test case is as follows:
- type: request_test_case
value:
# Which response this test corresponds to
response: 200
# Description of this test (optional)
description: "Test post user data"
# Overriding parameter values (optional)
# Defaults are taken from the parameters field of the operation
# But if listed here, it overrides the default
parameters:
- name: some_parameter
in: query
value: some_value
# Mock object outputs (optional)
# Used to declare the output content of certain objects; multiple can be declared
# Only its value will be retrieved in the test, requires additional handling through code
mocks:
- type: guzzle
value: post_200_v1_login
# Pre-test hook (optional)
# Called before the test is executed, can be given a string or an array of PHP callable definitions
setUp: ExampleClass::setUp
# Post-test hook (optional)
# Called after the test is executed, can be given a string or an array of PHP callable definitions
tearDown: ExampleClass::tearDown
# Request body (optional)
#
# Request format. This will affect how the request content should be encoded before sending.
# It will also generate the corresponding Header.
# Supports application/json, multipart/form-data, application/x-www-form-urlencoded
requestBody:
type: application/json
data:
# Directly write structured request content in the format of `key: string`.
username: "John"
# Or use `key: { type: file }` to upload a file
image:
type: file
path: ./uploaded_image.jpg
filename: original_name.jpg
# Or use `key: { type: array, data }` to represent an array
array_data:
type: array
data:
some_key: 1
some_other_key:
- a
- b
- c
use Goez\OpenAPI\Tester\TestSuite;
use Goez\OpenAPI\Tester\TestCase;
// Parse the entire API document to get the test suite
$testSuite = TestSuite::loadFromYamlFile(
__DIR__ . '/docs/api.yaml', // Document location
'My API Tests', // Test suite name
__DIR__ . '/test_files/' // External file path (Where to find the test files for testing uploads)
);
// Get warnings from the parsing process, which can be echoed to notify developers.
// Currently, warnings are generated when:
// - No tests are defined for an Operation
$warnings = $testSuite->getWarning();
// Retrieve the test cases
// An array of Goez\OpenAPI\Tester\TestCase
$testCases = $testSuite->getTestCases();
foreach ($testCases as $testName => $testCase) {
// Use the information contained in `$request` to make an HTTP call to your API or mock the Controller directly.
$request = $testCase->getRequest();
// Here, we use the fictitious function `callMyApi` to represent it. You'll need to implement it yourself.
// If you're using Laravel, more information is provided below.
$response = callMyApi($request);
// Here are some commonly used methods:
//
// $request->getPath();
// $request->getMethod();
// $request->getQuery();
// $request->getRequestBody();
// $request->getHeader();
// Verify if the actual response matches the definition
$result = $testCase->validate($response->code, $response->body, TestCase::FORMAT_JSON);
// Check if the validation was successful
assert($result->isValid(), true);
// Print out the validation details
echo $result->renderReport();
}
You can refer this file tests/Feature/OpenApiSchemaTest.php
.
Laravel doesn't actually send out HTTP requests, but instead creates a Request object and feeds it directly to the Laravel app for processing.
So, it's important to note the following:
- The request content doesn't need to be compiled into the actual format (JSON, urlencoded, etc); it can be directly inserted into the
$parameters
parameter in the form of a PHP array. - For file uploads, use the
Illuminate\Http\UploadedFile
object. Both the$parameters
and$files
fields should contain a copy. - You can use the
transformHeadersToServerVars
method built into Laravel TestCase to convert the header part of the request into the$server
variable. In this example, we convert the test request into a format that Laravel can easily digest:
public function extractRequestInfo(\Goez\OpenAPI\Tester\Request\Request $request): array
{
$files = [];
$body = [];
$server = $this->transformHeadersToServerVars($request->getHeader());
$requestBody = $request->getRequestBody();
if ($requestBody === null) {
return [$body, $files, $server];
}
$body = collect($requestBody->getStructuredData())
->map(function ($item, $name) use (&$files) {
if (is_a($item, \Goez\OpenAPI\Tester\Request\UploadedFile::class)) {
// Convert the `UploadedFile` object into the `Illuminate\Http\UploadedFile`
$uploadedFile = new \Illuminate\Http\UploadedFile(
$item->getPath(),
$item->getClientOriginalName(),
$item->getClientMimeType(),
null,
true
);
$files[$name] = $uploadedFile;
return $uploadedFile;
}
return $item;
})->toArray();
return [$body, $files, $server];
}