Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assertExactJson - False-Positive running #25960

Closed
sfatihk opened this issue Oct 5, 2018 · 10 comments
Closed

assertExactJson - False-Positive running #25960

sfatihk opened this issue Oct 5, 2018 · 10 comments

Comments

@sfatihk
Copy link

sfatihk commented Oct 5, 2018

  • Laravel Version: 5.7.7
  • PHP Version: 7.2.9
  • Database Driver & Version: MySQL 5.7.19
  • PHPUnit : 7.3.5

Description:

I saw this error message when testing my City Model resource show route.
Note: Database freshing after test. And i'm using sqlite for testing but i tested this situation on Mysql; anything change.


Error Message

PHPUnit 7.3.5 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 2.46 seconds, Memory: 18.00MB

There was 1 failure:

1) Tests\Unit\app\Http\Controller\Region\CityControllerTest::test_show_func_can_return_true_data
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'{"data":{"name":"West Fannieland","updated_at":"2018-10-05 20:48:11","created_at":"2018-10-05 20:48:11","id":1},"status":"success"}'
+'{"data":{"created_at":"2018-10-05 20:48:11","id":1,"name":"West Fannieland","updated_at":"2018-10-05 20:48:11"},"status":"success"}'

City Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class City extends Model
{
    protected $fillable = ['id','name'];
    
}

City Controller Show function

public function show(City $city)
    {
        return response()
            ->json([
                "status"=>"success",
                "data"=>$city
            ],200);
    }

Test Function

public function test_show_func_can_return_true_data()
    {
        $city = factory(App\City::class)->create();

        $this->json('GET', '/api/cities/'.$city->id)
            ->assertExactJson([
                'status' => 'success',
                'data' => $city
                ]);

    }

Beautified JSON response

Expected
{"data":{
    "name":"West Fannieland",
    "updated_at":"2018-10-05 20:48:11",
    "created_at":"2018-10-05 20:48:11",
    "id":1
},"status":"success"}

Actual
{"data":{
    "created_at":"2018-10-05 20:48:11",
    "id":1,
    "name":"West Fannieland",
    "updated_at":"2018-10-05 20:48:11"
},"status":"success"}

Exactly same data but different sorting. Why it acting like this ?

@sfatihk
Copy link
Author

sfatihk commented Oct 5, 2018

it works when I static defined.
All about sorting. Is sorting necessary?

public function test_show_func_can_return_true_data()
    {
        $city = factory(App\City::class)->create([
            "name" => "istanbul",
            "created_at" => "2018-10-15 21:35:46",
            "updated_at" => "2018-10-15 21:35:46"
        ]);

        $this->json('GET', '/api/cities/'.$city->id)
            ->assertExactJson([
                'status' => 'success',
                'data' => [
                    "created_at" => "2018-10-15 21:35:46",
                    "id" => 1,
                    "name" => "istanbul",
                    "updated_at" => "2018-10-15 21:35:46"
                ]
            ]);

    }

@svenluijten
Copy link
Contributor

This is because assertExactJson tries to match the given response to the expected array exactly. To test if the given JSON is present (with the attributes in any order), you can use assertJson.

@eric-addcream
Copy link

By definition, a json object is unordered.

An object is an unordered collection of zero or more name/value
pairs, where a name is a string and a value is a string, number,
boolean, null, object, or array.

Maybe the assertion should take that into account?

@dbudwin
Copy link

dbudwin commented Oct 19, 2018

I opened an issue the other week related to this as well #25769

I'm also having issues with assertExactJson due to array sorting. However, my issue manifests itself differently.

@alberthuang24
Copy link

I have repaired it and you can close the issues @sfatihk

@sfatihk
Copy link
Author

sfatihk commented Nov 13, 2018

Thank you for repair, my friend @HongjiangHuang .
I tested json example in your test case, thats works fine.

But the problem still exists on my test case.

I included your changes #26315, didn't work,
and then i tried on laravel last commit f83eca8, didn't work too .

Best way to test this situation seems like to still write manual json format & sorted values.

I simplified the problem.

public function test_show_func_can_return_true_city(){
  //city model( id, name )
  $city = App\City::create(['name'=>'Istanbul']);
  $city_from_db = App\City::find($city->id);

  $response = new TestResponse((new JsonResponse([$city])));

  $response->assertExactJson([$city_from_db]);
   //->assertJson([$city_from_db]);
  
  //$this->json('GET', '/api/cities/'.$city->id)->assertExactJson(['status' => 'success','data' => $city]);

}

output:

There was 1 failure:

1) Tests\Unit\app\Http\Controller\Region\CityControllerTest::test_show_func_can_return_true_city
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'[{"id":1,"name":"Istanbul","created_at":"2018-11-13 10:36:30","updated_at":"2018-11-13 10:36:30"}]'
+'[{"created_at":"2018-11-13 10:36:30","id":1,"name":"Istanbul","updated_at":"2018-11-13 10:36:30"}]'

C:\laragon\www\gs-api\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:461
C:\laragon\www\gs-api\tests\Unit\app\Http\Controllers\Region\CityControllerTest.php:41

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

@driesvints
Copy link
Member

I really don't see the problem here. I agree that the spec says it should be unordered by why don't you just use assertJson instead?

@alberthuang24
Copy link

alberthuang24 commented Nov 13, 2018

@sfatihk You can try

public function test_show_func_can_return_true_city(){
  //city model( id, name )
  $city = App\City::create(['name'=>'Istanbul']);
  $city_from_db = App\City::find($city->id);

  $response = new TestResponse((new JsonResponse([$city])));

  $response->assertExactJson([$city_from_db->toArray()]);
}

@sfatihk
Copy link
Author

sfatihk commented Nov 13, 2018

I really don't see the problem here. I agree that the spec says it should be unordered by why don't you just use assertJson instead?

assertjson was printing same error.


@sfatihk You can try

public function test_show_func_can_return_true_city(){
  //city model( id, name )
  $city = App\City::create(['name'=>'Istanbul']);
  $city_from_db = App\City::find($city->id);

  $response = new TestResponse((new JsonResponse([$city])));

  $response->assertExactJson([$city_from_db->toArray()]);
}

Thanks again my friend, @HongjiangHuang
toArray() suggestion and your pr, fixed this issue.

@sfatihk sfatihk closed this as completed Nov 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants