如何测试 RESTful api 在 POST 中传递数据?
How to test RESTful api passing data in POST?
我需要从 cli 测试我的 php API。
这是我的php脚本test.php:
<?php
$request = new Request();
if (isset($_SERVER['PATH_INFO'])) {
$request->url_elements = explode('/', trim($_SERVER['PATH_INFO'], '/'));
}
$request->method = strtoupper($_SERVER['REQUEST_METHOD']);
switch ($request->method) {
case 'GET':
$request->parameters = $_GET;
break;
case 'POST':
$request->parameters = $_POST;
break;
case 'PUT':
parse_str(file_get_contents('php://input'), $request->parameters);
break;
}
print $request->method . ": "; print_r($request->parameters); # DEBUG
?>
这是我的尝试,使用 curl(如网络上广泛记录的那样...):
$ curl -X POST -H "Content-type: application/json" -d '{"key":"value"}' http://localhost/test.php
这是结果:
_GET: Array
(
)
_POST: Array
(
)
我希望 "key: value" 在 _POST
...
我错过了什么?
P.S.: 抱歉,我知道我犯了一些非常愚蠢的错误,我觉得自己很愚蠢...:-(
您正在发布 JSON 但试图解释 urlform 编码的数据。你应该使用 $postdata = file_get_contents("php://input");
您不应该以这种方式测试 REST API。测试代码不得包含任何 URI 结构。通过 REST 客户端,您始终必须遵循 API 给出的 link,并根据元数据(例如 link 关系、RDF 等找到正确的 link。 ..) 附在上面。如果您不能遵循基本的 REST constraints(在这种情况下为统一接口约束),为什么将您的 API 称为 REST?
在你的情况下 GET http://example.com/api/v1/
应该 return 一个 link 像这样的东西:
{
relation: "http://example.com/api/v1/docs/createItem"
uri: "http://example.com/api/v1/",
method: "POST",
headers: {
contentType: "application/json"
},
data: {
key: "value"
}
}
您的测试代码应该与此类似:
$apiRoot = 'http://example.com/api/v1/'
$response1 = getHttp($apiRoot);
expect($response1->headers->statusCode)->toBe(200);
$data1= parseJson($response1);
$link2 = findLinkByRelation($data1, $apiRoot.'docs/myCollection/createItem');
$response2 = followLink($link2);
expect($response2->headers->statusCode)->toBe(201);
$data2 = parseJson($response2);
$link3 = findLinkByRelation($data2, $apiRoot.'docs/myCollection/getItem');
$response3 = followLink($link3);
expect($response3->headers->statusCode)->toBe(200);
$data3 = parseJson($response3);
expect($data3)->containProperty(array("key" => "value"));
这样测试代码将像真实客户端一样松散耦合到服务实现,因此它可以用作真实客户端的模板。
顺便说一句。这称为服务的端到端测试。如果在测试中覆盖超全局变量(如 $_SERVER、$_POST 等)来模拟 HTTP 部分,则可以使其更快。
哦,我读到了你的问题。 $_POST 只解析 application/x-www-form-urlencoded
和 multipart/form-data
。所以你必须通过输入流获取原始 post 数据并手动解析它,但你真正需要的是一个 HTTP 框架,例如http://www.slimframework.com/ , http://symfony.com/ 等...自动执行此操作。但这与您应该如何测试 API 无关。 :-)
我需要从 cli 测试我的 php API。
这是我的php脚本test.php:
<?php
$request = new Request();
if (isset($_SERVER['PATH_INFO'])) {
$request->url_elements = explode('/', trim($_SERVER['PATH_INFO'], '/'));
}
$request->method = strtoupper($_SERVER['REQUEST_METHOD']);
switch ($request->method) {
case 'GET':
$request->parameters = $_GET;
break;
case 'POST':
$request->parameters = $_POST;
break;
case 'PUT':
parse_str(file_get_contents('php://input'), $request->parameters);
break;
}
print $request->method . ": "; print_r($request->parameters); # DEBUG
?>
这是我的尝试,使用 curl(如网络上广泛记录的那样...):
$ curl -X POST -H "Content-type: application/json" -d '{"key":"value"}' http://localhost/test.php
这是结果:
_GET: Array
(
)
_POST: Array
(
)
我希望 "key: value" 在 _POST
...
我错过了什么?
P.S.: 抱歉,我知道我犯了一些非常愚蠢的错误,我觉得自己很愚蠢...:-(
您正在发布 JSON 但试图解释 urlform 编码的数据。你应该使用 $postdata = file_get_contents("php://input");
您不应该以这种方式测试 REST API。测试代码不得包含任何 URI 结构。通过 REST 客户端,您始终必须遵循 API 给出的 link,并根据元数据(例如 link 关系、RDF 等找到正确的 link。 ..) 附在上面。如果您不能遵循基本的 REST constraints(在这种情况下为统一接口约束),为什么将您的 API 称为 REST?
在你的情况下 GET http://example.com/api/v1/
应该 return 一个 link 像这样的东西:
{
relation: "http://example.com/api/v1/docs/createItem"
uri: "http://example.com/api/v1/",
method: "POST",
headers: {
contentType: "application/json"
},
data: {
key: "value"
}
}
您的测试代码应该与此类似:
$apiRoot = 'http://example.com/api/v1/'
$response1 = getHttp($apiRoot);
expect($response1->headers->statusCode)->toBe(200);
$data1= parseJson($response1);
$link2 = findLinkByRelation($data1, $apiRoot.'docs/myCollection/createItem');
$response2 = followLink($link2);
expect($response2->headers->statusCode)->toBe(201);
$data2 = parseJson($response2);
$link3 = findLinkByRelation($data2, $apiRoot.'docs/myCollection/getItem');
$response3 = followLink($link3);
expect($response3->headers->statusCode)->toBe(200);
$data3 = parseJson($response3);
expect($data3)->containProperty(array("key" => "value"));
这样测试代码将像真实客户端一样松散耦合到服务实现,因此它可以用作真实客户端的模板。
顺便说一句。这称为服务的端到端测试。如果在测试中覆盖超全局变量(如 $_SERVER、$_POST 等)来模拟 HTTP 部分,则可以使其更快。
哦,我读到了你的问题。 $_POST 只解析 application/x-www-form-urlencoded
和 multipart/form-data
。所以你必须通过输入流获取原始 post 数据并手动解析它,但你真正需要的是一个 HTTP 框架,例如http://www.slimframework.com/ , http://symfony.com/ 等...自动执行此操作。但这与您应该如何测试 API 无关。 :-)