0

I am trying to test a Laravel REST API, through phpunit. While testing REST calls, I am unable to isolate REST calls test.

In Laravel, I understand a few options like using traits DatabaseMigrations, DatabaseRefresh, DatabaseTransactions. But I can't use these for the following reasons:

  • DatabaseMigrations: The app does not have proper migrations. Even if it had, those would be quite in-efficient.

  • DatabaseRefresh: Same as above.

  • DatabaseTransactions. The problem I see is that call to HTTP API is a completely different process. These are not within the same transaction. So a test that inserts data to setup the test case is not seen by HTTP call. Also, if data is inserted by HTTP calls like will be visible to other tests.

I can't write unit tests without calling HTTP; the app is not written in such a way. Entire code is in Routes or in Controller is not otherwise testable.

4
  • If you don't have your planned production database structured in a way which doesn't comply with sqlite - then working on defining proper migrations will be a good step. Then you can use in-memory sqlite for testing with DatabaseMigrations or RefreshDatabase and the tests will still be pretty fast - just a thought Commented Dec 27, 2020 at 19:51
  • @Donkarnash It will be pretty hard to create migrations of an entire schema, though not impossible. I will give it a try once I find a tool that does that automatically, I mean take a sql and convert it to Laravel Migration/Seeder. However I am still looking for a solution that perhaps deals with Transactions. That is perhaps the path of least resistance. Commented Dec 28, 2020 at 9:25
  • 1
    Can you explain why is the API Call a completely different transaction? Have you try to write a simple test case? if so, can you show us the code? Commented Jan 28, 2021 at 9:23
  • I think the misconception you have is that you intend to call the API using a HTTP request over the network. In Laravel, you have HTTP Tests for that, see the docs at laravel.com/docs/8.x/http-tests for more info. The whole idea with testing is that you always use mock instances. How else would you prevent the application from triggering real-life events or writing to your dev or even production database instead of the test DB? Commented Jan 30, 2021 at 19:25

2 Answers 2

0

i test my my endpoints with the json function ( i believe there is a POST and GET method as well, but i need to pass in data and headers)

public function test_endpoint() {
        $result = $this->json('POST', '/api', ['key' => 'data'], ['Header' => "Value"]);
}

i have unit and feature tests as well, but i use this for testing graphQL endpoint.

Sign up to request clarification or add additional context in comments.

Comments

0

So in my example void means that our method does not returning anything. postJson means we expect JSON response, either we can do just $this->post()

You can make calls like this

public function test_create_order() : void
    {
        $response = $this->postJson('/make-order',[
            'foo' => 'bar',
            'baz' => 'bat'
        ]);

        // To make sure it is returning 201 created status code, or other code e.g. (200 OK)
        $response->assertStatus(201);

        // To make sure it is in your desired structure 
        $response->assertJsonStructure([
                'id',
                'foo',
                'baz',
        ]);
 
        // Check if response contains exactly that value, what we inserted
        $this->assertEquals('bar', $response->json('data.foo'));

        // Check that in the database created that record,
        // param 1 is table name, param 2 is criteria to find that record
        // e.g. ['id' => 1]
        $this->assertDatabaseHas('orders', [
            'foo' => 'bar'
        ]);
        // Also there is other method assertDatabaseMissing, that works like above
        // just in reverse logic, it is checking that there is no record with that criteria
       
    }

1 Comment

Deleting orders from other tests within a test a bit strange, you can use DatabaseTransactions to leave the database in an untouched state.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.