Laravel 尝试对 API JSON 响应进行单元测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25190451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:55:13  来源:igfitidea点击:

Laravel Trying To Unit Test API JSON Response

phpunit-testinglaravelphpunit

提问by Shane

Trying to learn too many new things at once here (Laravel, PHPUnit, etc), so this is probably just a tired brain problem, would still appreciate some help.

试图在这里一次学习太多新东西(Laravel、PHPUnit 等),所以这可能只是一个累脑的问题,仍然希望得到一些帮助。

I have a very basic 'Blog' project using Laravel as the API layer and AngularJS as the front end. I want to unit test the API end-points but I am having trouble figuring out how to process JSON while in my test functions.

我有一个非常基本的“博客”项目,使用 Laravel 作为 API 层,使用 AngularJS 作为前端。我想对 API 端点进行单元测试,但是在我的测试函数中我无法弄清楚如何处理 JSON。

When I try to run testGetBlogPosts() I see what looks like the JSON output in my CLI, but I am unable to json_decode() and check that certain parts of the object match my expected result. Here I simply want to make sure that the ID on the first object in the result array is ID "1".

当我尝试运行 testGetBlogPosts() 时,我看到 CLI 中的 JSON 输出看起来像什么,但我无法 json_decode() 并检查对象的某些部分是否与我的预期结果匹配。在这里,我只想确保结果数组中第一个对象的 ID 是 ID“1”。

The result I receive from the test is: 1) ExampleTest::testGetBlogPosts ErrorException: Trying to get property of non-object

我从测试中收到的结果是:1) ExampleTest::testGetBlogPosts ErrorException: Trying to get property of non-object

Any help or suggestions is much appreciated!

非常感谢任何帮助或建议!

TL;DR: Test case is not correctly processing JSON response from API endpoint

TL;DR:测试用例未正确处理来自 API 端点的 JSON 响应

Controller

控制器

class HomeController extends BaseController {

    /*
    |--------------------------------------------------------------------------
    | Default Home Controller
    |--------------------------------------------------------------------------
    |
    | You may wish to use controllers instead of, or in addition to, Closure
    | based routes. That's great! Here is an example controller method to
    | get you started. To route to this controller, just add the route:
    |
    |   Route::get('/', 'HomeController@showWelcome');
    |
    */
    public function showWelcome()
    {
        return View::make('hello');
    }

    public function getBlogPosts()
    {
        $posts = Post::get()->take(5)->toJson();
        // echo $posts; PER THE ACCEPTED ANSWER, RETURN NOT ECHO
        return $posts;
    }
    public function getSinglePost($postId)
    {
        $posts = Post::find($postId)->toJson();
        // echo $posts; PER THE ACCEPTED ANSWER, RETURN NOT ECHO
        return $posts;
    }

}

Test File

测试文件

class ExampleTest extends TestCase {

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $crawler = $this->client->request('GET', '/');
        $this->assertTrue($this->client->getResponse()->isOk());
    }

    public function testGetBlogPosts()
    {
        $response = $this->call('GET', 'api/getBlogPosts');

        $array = json_decode($response);
        $result = false;
        if($array[0]->id == 1)
        {
            $result = true;
        }
        $this->assertEquals(true, $result);
    }
}

As requested, the full test output

根据要求,完整的测试输出

root@homestead:/home/vagrant/Laravel/Homestead/Blog# phpunit PHPUnit 3.7.28 by Sebastian Bergmann.

Configuration read from /home/vagrant/Laravel/Homestead/Blog/phpunit.xml

.E[{"id":"1","user_id":"1","title":"This is a test post","post_body":"testststs","created_at":"2014-08-07 19:26:26","updated_at":"2014-08-07 19:26:26"},{"id":"2","user_id":"75","title":"Libero rerum rem praesentium et et at doloribus asperiores.","post_body":"Commodi aut beatae aut veritatis eum soluta sint. In aut cumque iure quis.","created_at":"2014-08-07 19:26:26","updated_at":"2014-08-07 19:26:26"}]

Time: 1.85 seconds, Memory: 18.50Mb

There was 1 error:

1) ExampleTest::testGetBlogPosts ErrorException: Trying to get property of non-object

/home/vagrant/Laravel/Homestead/Blog/app/tests/ExampleTest.php:22

FAILURES! Tests: 2, Assertions: 1, Errors: 1.

root@homestead:/home/vagrant/Laravel/Homestead/Blog# phpunit PHPUnit 3.7.28 by Sebastian Bergmann。

从 /home/vagrant/Laravel/Homestead/Blog/phpunit.xml 读取的配置

.E[{"id":"1","user_id":"1","title":"这是一个测试帖子","post_body":"testststs","created_at":"2014-08-07 19:26:26","updated_at":"2014-08-07 19:26:26"},{"id":"2","user_id":"75","title":"Libero rerum rem praesentium et at doloribus asperiores.","post_body":"Commodi aut beatae aut veritatis eum soluta sint。在 aut cumque iure quis.","created_at":"2014-08-07 19:26:26","updated_at ":"2014-08-07 19:26:26"}]

时间:1.85 秒,内存:18.50Mb

有 1 个错误:

1) ExampleTest::testGetBlogPosts ErrorException: 试图获取非对象的属性

/home/vagrant/Laravel/Homestead/Blog/app/tests/ExampleTest.php:22

失败!测试:2,断言:1,错误:1。

If I go to this endpoint in a browser I get this

如果我在浏览器中访问这个端点,我会得到这个

[
{
id: 1,
user_id: 1,
title: "This is a test post",
subtitle: "",
post_body: "testststs",
created_at: "2014-08-07 19:26:04",
updated_at: "2014-08-07 19:26:04"
},
{
id: 2,
user_id: 18,
title: "Rem deserunt dolor odit tempore qui eaque labore.",
subtitle: "",
post_body: "Ea a adipisci molestiae vel dignissimos. Ea blanditiis et est.",
created_at: "2014-08-07 19:26:04",
updated_at: "2014-08-07 19:26:04"
}
]

采纳答案by Don't Panic

The getBlogPosts()method in your controller echos $postrather than returning it. This means that the $responsein your test will not have anything in it to json_decode.

getBlogPosts()控制器中的方法会回显$post而不是返回它。这意味着$response在您的测试中将没有任何内容 to json_decode

回答by vladsch

Hope you figured it out by now but here is what I use:

希望你现在已经弄清楚了,但这是我使用的:

$array = json_decode($response->getContent());

$array = json_decode($response->getContent());

回答by hpaknia

Adding a method in /tests/TestCase.phphelps a lot:

添加一个方法/tests/TestCase.php有很大帮助:

/**
 * dumps json result
 * @param string $function can be print_r, var_dump or var_export
 * @param boolean $json_decode 
 */
public function dump($function = 'var_export', $json_decode = true) {
    $content = $this->response->getContent();
    if ($json_decode) {
        $content = json_decode($content, true);
    }
    // ? ? ? ★ ☆ ? ? ? ?  ? ∞ ? ? ? ?
    $seperator = '? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?';
    echo PHP_EOL . $seperator . PHP_EOL;
    $function($content);
    echo $seperator . PHP_EOL;
    return $this;
}

Then you can call it at any point after json call:

然后你可以在 json 调用后的任何时候调用它:

public function testInvalidPostID() {
    $this->json('PUT', '/posts/2222/sh-comments/1001', [
        'input' => 'SomeThing'
            ], [
        'Authorization' => 'Bearer ' . app('jwt')->getTokenForUser(2)
    ])->dump() //dumpnig output as array
      ->seeJsonStructure(['errors' => [
            '*' => [
                'message'
            ]
        ]
    ])->assertResponseStatus(404);
}

回答by Jeff Puckett

You can call the jsonmethod directly off the response object.

您可以json直接从响应对象调用该方法。

$response = $this->getJson('/foo');
$json = $response->json(); // ['foo' => 'bar', 'baz' => 'boo']

It also accepts a key as an argument.

它还接受一个键作为参数。

$foo = $response->json('foo'); // 'bar'