manshu's avatar
Level 28

Creating User for API giving error

Here's my User Registration Test. I am using default UserFactory.php to create user. I am getting the following error.

Illuminate\Validation\ValidationException: The given data was invalid.

<?php

namespace Tests\Feature\API\Users;

use Tests\TestCase;
use WebApp\Domain\Users\User;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class UsersFeatureTest extends TestCase
{
    
    use RefreshDatabase;

    /** @test */
    public function it_registers_new_user_using_api()
    {
        $this->withoutExceptionHandling();
        //Given
        $user = factory(User::class)->create()->toArray();
        //When
        $response = $this->post('/api/register', $user);
        //Then
        $response->assertStatus(201);
    }

}

0 likes
20 replies
manshu's avatar
Level 28

@tisuchi Nope doesn't work. It's redirecting from that page automatically.

Expected status code 201 but received 302.
Failed asserting that false is true.
tisuchi's avatar

@manshu

You know what, it actually works.

Now it shows a different message.

It means, you expect 201 status code, however, you get 302. That means you are redirecting to other pages.

I guess its because you have redirecting the visitor to another page after signed up successfully.

You may show your method code.

manshu's avatar
Level 28

Here you go @tisuchi


    public function store(Request $request)
    {
        $this->validate($request, [
            "name" => 'required',
            "email" => 'email|required|unique:users,email',
            "password" => 'required',
        ]);


        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
        ]);

        return response()->json([
            "status" => "Success"
        ], 201);
        
    }

tisuchi's avatar

@manshu

I found the redirect code in your method is the validation part. It may be because of failing the validation part and redirect.

To confirm that, you may take off the validation part from your method and try. It should be like that-

public function store(Request $request)
    {

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
        ]);

        return response()->json([
            "status" => "Success"
        ], 201);
        
    }

Now run the test.

manshu's avatar
Level 28

If i remove validation, how i validate user data?

bugsysha's avatar
$response = $this->post('/api/register', $user);

should be

$response = $this->postJson('/api/register', $user);
tisuchi's avatar

@manshu

I am not telling you to remove completely. I just want to investigate only why you are getting 302. If you are confirmed that, it's because of validation, ofcourse there is a way to fix it.

:)

manshu's avatar
Level 28

After i removed that, i am getting following errors.

There was 1 error:

1) Tests\Feature\API\Users\UsersFeatureTest::it_registers_new_user_using_api
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: users.email (SQL: insert into "users" ("name", "email", "password", "updated_at", "created_at") values (Dameon Reinger MD, [email protected], y$zjDqfWrC.5xFVIXWC05TAeM8kYDbxwG9g3t30en0Zi70d/w41HoTa, 2019-12-01 17:59:50, 2019-12-01 17:59:50))
manshu's avatar
Level 28

Nope. Simple Create User Test isn't working. Idk what im doing wrong. I keep getting 422 error for invalid data.

manshu's avatar
Level 28

My test

     
  /** @test */
    public function it_registers_new_user_using_api()
    {
        $this->withoutExceptionHandling();
        //Given
        $user = factory(User::class)->create()->toArray();
        //When
        $response = $this->postJson('/api/register', $user);
        //Then
        $response->assertStatus(201);
    }

My factory

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => 'yIXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
   
    ];
});

My controller


    public function store(Request $request)
    {
        $this->validate($request, [
            "name" => 'required',
            "email" => 'email|required|unique:users,email',
            "password" => 'required',
        ]);


        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
        ]);

        return response()->json([
            "status" => "Success"
        ], 201);
        
Nakov's avatar
Nakov
Best Answer
Level 73

@manshu you are trying to create a user, and then post the created user to be registered. So it is failing on the email being unique more likely. Try this instead:

/** @test */
public function it_registers_new_user_using_api()
{
    //Given
    $user = factory(User::class)->raw();
    //When
    $response = $this->postJson('/api/register', $user);
    //Then
    $response->assertStatus(201);
}
goldtaste's avatar

Check out : https://laravel.com/docs/5.8/http-tests#testing-json-apis

So instead of

 $response = $this->postJson('/api/register', $user);

do

$response = $this->json('POST', '/api/register', ['name' => 'Sally', 'email' => '[email protected]', 'password' => 'mypassword']);

You are going to have to pass some valid data if you want the test to pass. You should also write a test where you pass invalid data and check for an exception. 422? 403?

manshu's avatar
Level 28

Yess !!!! raw() function worked. Thanks guys. I totally forgot about that.

goldtaste's avatar

Ahh, sorry. Didn't spot that you were posting the user. Yes, @nakov answer makes the most sense. You created the user and then tried to re-register them.

bugsysha's avatar

@manshu you can also use make() and cast it to array. So the redirect was due to create() or not using postJson()?

Please or to participate in this conversation.