Timestamps are making my phpunit tests fail
Asked Answered
D

4

5

When I use the following PostResource, and Post Test, my tests succeed:

PostResource.php

public function toArray($request)
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'content' => $this->content,
        'slug' => $this->slug,
    ];
}

PostController.php

public function show(Post $post)
{
    return new PostResource($post);
}

ReadPostTest.php

/** @test */
public function a_user_can_read_a_single_post()
{
    $post = factory(Post::class)->create([
        'title' => 'A new post',
        'content' => "Some content",
        'slug' => "a-new-post",
    ]);

    //dd($post);

    $response = $this->json('GET', '/posts/' . $post->id)
            ->assertStatus(200)
            ->assertJsonFragment([ 'data' => [
                'title' => 'A new post',
                'content' => "Some content",
                'slug' => "a-new-post",
            ]]);

}

When I add created_at and updated_at to my tests and resource I get a failure. The test bellow show when I didn't add .000000Z.

phpunit

There was 1 failure:

1) Tests\Feature\ReadPostsTest::a_user_can_read_a_single_post
Unable to find JSON: 

[{
    "data": {
        "title": "A new post",
        "content": "Some content",
        "slug": "a-new-post",
        "created_at": "2018-12-06 21:13:26",
        "updated_at": "2018-12-06 21:13:26"
    }
}]

within response JSON:

[{
    "data": {
        "id": 1,
        "title": "A new post",
        "content": "Some content",
        "slug": "a-new-post",
        "created_at": "2018-12-06T21:13:26.000000Z",
        "updated_at": "2018-12-06T21:13:26.000000Z"
    }
}].


Failed asserting that an array has the subset Array &0 (
    'data' => Array &1 (
        'title' => 'A new post'
        'content' => 'Some content'
        'slug' => 'a-new-post'
        'created_at' => '2018-12-06 21:13:26'
        'updated_at' => '2018-12-06 21:13:26'
    )
).
--- Expected
+++ Actual
@@ @@
     'title' => 'A new post',
     'content' => 'Some content',
     'slug' => 'a-new-post',
-    'created_at' => '2018-12-06 21:13:26',
-    'updated_at' => '2018-12-06 21:13:26',
+    'created_at' => '2018-12-06T21:13:26.000000Z',
+    'updated_at' => '2018-12-06T21:13:26.000000Z',
   ),
 )

I tried adding 000000Z that and got the same problems.

There was 1 failure:

1) Tests\Feature\ReadPostsTest::a_user_can_read_a_single_post
Unable to find JSON fragment: 

[{"data":{"content":"Some content","created_at":"2019-12-20 21:42:33.000000Z","id":1,"slug":"a-new-post","title":"A new post","updated_at":"2019-12-20 21:42:33.000000Z"}}]

within

[{"data":{"content":"Some content","created_at":"2019-12-20T21:42:33.000000Z","id":1,"slug":"a-new-post","title":"A new post","updated_at":"2019-12-20T21:42:33.000000Z"}}].
Failed asserting that false is true.

It seems like my created_at and up_dated at timestamps are messed up for a reason that I have no idea why? 2019-12-20T21:42:33.000000ZThat's probably what's getting my tests to fail. How do I fix this?

Disseminate answered 20/12, 2019 at 22:6 Comment(1)
z is zone identifier and maybe you add z somewhereUndone
P
3

You probably want to use Carbon's setTestNow() to fix what 'now' means during the test.

Written with the assumption you are using Laravel.

// Immutable, so you don't go insane.
$now = \Carbon\CarbonImmutable::now()->micro(0);

// Fix Carbon's 'now' to that time
\Illuminate\Support\Carbon::setTestNow($now)
// \Carbon\CarbonImmutable::setTestNow($now);

// Your tests here
// u = microseconds, but it's not set to '000000' in 'now', if you forget `->micro(0)`.
// The 'Y-m-d\TH:i:s.u\Z' format works with Laravel 6.20.19 in march 2021, but YMMV.
// ->assertJSon(['created_at' => $now->utc()->format('Y-m-d\TH:i:s.000000\Z'),])

// Release Carbon's 'now' time to follow your clock again.
\Illuminate\Support\Carbon::setTestNow(null)
// \Carbon\CarbonImmutable::setTestNow(null);
Plutonic answered 24/3, 2021 at 10:15 Comment(2)
To release Carbon's now, you should set it to null: \Illuminate\Support\Carbon::setTestNow(null);Moratorium
Thanks @Sebj, I changed my example code.Plutonic
D
3

It looks like you're struggling with the timestamps format. I had the same issue and solved it through the JSON serialization, found in the Carbon documentation. In your case, it must look like this:

public function a_user_can_read_a_single_post()
{
    $post = factory(Post::class)->create([
        'title' => 'A new post',
        'content' => "Some content",
        'slug' => "a-new-post",
        "updated_at" => Carbon::now()->timestamp,
        "created_at" => Carbon::now()->timestamp
    ]);

    $response = $this->json('GET', '/posts/' . $post->id)
            ->assertStatus(200)
            ->assertJsonFragment([ 'data' => [
                'id' => 1,
                'title' => 'A new post',
                'content' => "Some content",
                'slug' => "a-new-post",
                "updated_at" => $post->updated_at->jsonSerialize(),
                "created_at" => $post->created_at->jsonSerialize()
            ]]);

}

It may be a little late, but hopefully helps to others. Good luck buddy.

Deceased answered 25/10, 2021 at 0:7 Comment(0)
D
1

Use carbon on your post model factory and then use $post->created_at and $post->updated_at in the json assertion:

public function a_user_can_read_a_single_post()
{
    $post = factory(Post::class)->create([
        'title' => 'A new post',
        'content' => "Some content",
        'slug' => "a-new-post",
        "updated_at" => Carbon::now()->timestamp,
        "created_at" => Carbon::now()->timestamp
    ]);

    //dd($post);

    $response = $this->json('GET', '/posts/' . $post->id)
            ->assertStatus(200)
            ->assertJsonFragment([ 'data' => [
                'id' => 1,
                'title' => 'A new post',
                'content' => "Some content",
                'slug' => "a-new-post",
                "updated_at" => $post->updated_at,
                "created_at" => $post->created_at
            ]]);

}

For some reason a string of timestamps doesn't work. Hopefully someone else can comment as to why.

Disseminate answered 20/12, 2019 at 22:20 Comment(0)
H
0

It works for me when I do this (Note: I put the date with ones to simplify the process):

use Carbon\Carbon;
        
class ExampleTest extends TestCase
{
  protected function setUp(): void
  {
    Carbon::setTestNow(Carbon::create(1111, 1, 11, 11));
  }
        
  /** @test */
  public function your_awesome_test()
  {
    $this->postJson(route('route.name'),[
      'title' => 'A new post',
      'content' => "Some content",
      'slug' => "a-new-post",
    ])->assertJsonFragment([ 
      'data' => [
         'id' => 1,
         'title' => 'A new post',
         'content' => "Some content",
         'slug' => "a-new-post",
         "updated_at" => Carbon::setTestNow(),
         "created_at" => Carbon::setTestNow()
      ]
    ];
  }
}
Hear answered 26/1, 2023 at 20:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.