-
Notifications
You must be signed in to change notification settings - Fork 11k
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
Response status should be 200 instead of 201 when returned model was created from within a test before making the request #25868
Comments
Update: Mixed up two of the issues. It actually works when calling |
Why are you doing |
@laurencei because without the call to Forget |
You are returning a |
No. It's smarter than that. Test also fails if i omit the UserResource and just As can be seen in the PR #21625 (which i assume is causing the issue), it checks against |
In the internals of a ResourceResponse I see the following piece of code: /**
* Calculate the appropriate status code for the response.
*
* @return int
*/
protected function calculateStatus()
{
return $this->resource->resource instanceof Model &&
$this->resource->resource->wasRecentlyCreated ? 201 : 200;
} Because the user was "recently created" with the factory you'll get back a 201 status code. If you want to get back a 200 status code and mimic a user which already existed you'll have to set the It's only possible to do this beforehand because it's just the way resources work for new models so the developer doesn't needs to worry about which status code he's going to have to return. |
@driesvints - but if the model was created inside a factory before the request - then returning I havent fully tested - but this looks like a bug to me. |
@laurencei It's probably best to open a new issue then because it's unrelated to resource responses or status codes. |
@driesvints my issue description doesn't mention Resources at all – it's just using typical example code containing a Resource. It is mentioned in the description that the issue is around |
…but i still agree with you, @driesvints – it should be clear in the issue title and description that the issue is |
@laurencei are you opening a new issue or do you want me to do so? |
You can do it @jsphpl . I'm testing on a fresh 5.7 install - and I can replicate the issue ... but I'm not sure what the fix is. Open the ticket and i'll talk there. |
@jsphpl yes you did. But to be honest I don't see a bug here anywhere at all. I believe that for testing I'll re-open this issue to let @taylorotwell have a look to see what he has to say, no need to create a new issue. Sorry for the confusion. |
Not sure if i read you correctly, but the issue also exists when i just
I think the test i posted initially should pass. And as it doesn't pass, i think there is a bug. My point is: It's only half cool if Laravel is only half smart. Don't get me wrong, i love its smartness, but i'd love it even more if it was fully smart. That would mean for me, the developer, that i don't have to work around Laravel thinking a resource was created within the request/response lifecycle when it was actually created before the request. So it's not a critical bug, but some potential for full smartness and even more developer joy. |
So fresh install of Laravel 5.7:
and
gives a This is a bug - because the user existed before the start of the reqeust. i.e. we did not create a new user and return it inside of The problem seems to be |
I still don't consider it a bug because you did create the user just before you made the request. We could change the default behavior of factories to not indicate newly created models as such but I think that would be a breaking change. |
@driesvints yeah but just before is not during. So this is basically a discussion of whether |
Remember the point of 201 is the request was successful and you created a resource. But it The fact I created a |
Anyway - 2 ways to approach this:
|
Number 2 seems a valid point to me 👍 |
Makes perfect sense to me. Can't fully wrap my head around it, but what if authentication happens against a third party? In that case, the server doesn't necessarily need to have prior knowledge about the user? But not sure if that matters in the context of |
But for I've done a PR with a proposed fux |
Great, thanks a lot! |
use: $user = factory(User::class)->create();
Passport::actingAs(User::find($user->id)); This will return 200. |
Description:
In a PHPUnit test, when creating a User through a factory and returning Auth::user() from a controller/action, the response status is 201, where it should be 200.
This was addressed in #21107 #25775 and #23270 (and probably others). However, the suggested solution of
->refresh()
ing the user before passing it to->actingAs()
doesn't work for me. Further, i think it should not be necessary to refresh the user in order to work around the framework trying to be smart. It's not difficult to manually set the response status to 201 in an endpoint where a fresh resource is created. So the "smartness" of wasRecentlyCreated resulting in a 201 status code is not that valuable. Especially if it's only half smart and doesn't distinguish between resources created within the request/response lifecycle and resources created by a test before making the request.I consider the following scenario a valid test that should actually pass. If you agree on that, let's look for a solution together. If you don't agree that the test should pass, feel free to close this issue, and sugggest a reliable approach to get the proper status code that is consistent between test and production environment.
Steps to reproduce:
1. Create a test case:
2. Create the corresponding action:
3. Run the test
4. Call
->refresh()
on the user before passing it toactingAs()
Contrary to what was suggested as a solution in one of the quoted issues, even with the
refresh()
call, the test fails for me:The text was updated successfully, but these errors were encountered: