Laravel test returns 404 - laravel

I'm trying to run some tests but it is returning 404 after the first run. Sometimes it runs normally, but 90% of the time, it returns me a 404 response.
Pstoman request works 100% of the time.
First time running (the failure here is from another test):
Next times (now I'm getting the 404):
Here is my phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="APP_URL" value="http://localhost"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
The test:
public function verify_username_should_return_id_when_existing_document()
{
$this->seed(UserTypeSeeder::class);
$user = User::factory()->create();
$response = $this->withHeaders([
'user_type' => $user->type->id,
])->postJson("api/auth/username", [
"username" => $user->document
]);
$response->assertOk()
->assertJson(["id" => 1]);
}

I found that for some reason if I change the $this->withHeaders(['user_type' => $user->type->id,]) to $this->withHeader("user_type", $user->type->id) it works but it doesn't make sense to me

Related

I got “There is no active transaction” error after I added RefreshDatabase into test file

Making in laravel 9.48.0 with mysql database http tests after I added RefreshDatabase into test file
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Foundation\Testing\Concerns\InteractsWithExceptionHandling;
use Tests\TestCase;
use App\Models\{Article, User};
use Illuminate\Support\Str;
class ArticlesCrudTest extends TestCase
{
use InteractsWithExceptionHandling;
use RefreshDatabase;
I got “There is no active transaction” error on 1st test from 15 tests in this file
I do not use sqllite, but other mysql database, so phpunit.xml have sqlite and memory options disabled:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
printerClass="Sempro\PHPUnitPrettyPrinter\PrettyPrinterForPhpUnit9"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
My control have code :
\Log::info( ' -1 store::');
DB::beginTransaction();
try {
$article = Article::create([
'title' => $data['title'],
'text' => $data['text'],
'text_shortly' => $data['text_shortly'],
'creator_id' => $data['creator_id'],
'published' => $data['published'],
]);
\Log::info( ' -2 store::');
DB::Commit();
$article->load('creator');
return response()->json(
['article' => (new ArticleResource($article))],
HTTP_RESPONSE_OK_RESOURCE_CREATED
); // 201
} catch (\Exception $e) {
DB::rollback();
}
In log file there are 2 lines from this controller. Before I added RefreshDatabase these tests worked ok, just like in real work.
What is wrong ?
Thanks!

Laravel DatabaseMigration not running migrations

I'm trying to create a very simple test, where it calls a service function that executes an ::all function in a model.
EDIT: As mentioned in a comment, I put it as a feature test, but still same issue:
namespace Tests\Feature;
use App\Models\FlashCard;
use App\Services\FlashCardService;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
/**
* A basic test example.
*
* #return void
*/
public function test_the_application_returns_a_successful_response()
{
$flashCardService = new FlashCardService();
$flashCardService::getAll();
}
}
The getAll() function all it does is:
public static function getAll(): Collection {
return FlashCard::all(['id', 'question', 'answer', 'status']);
}
The problem is that I get an error that the is no such table
General error: 1 no such table: flash_cards so the DatabaseMigrations is not running.
My phpunit.xml looks like this
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
Any ideas?

Apply phpunit.xml setting for speific classes only

I have the following setting in my phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<testsuites>
<testsuite name="Application Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
</php>
</phpunit>
How can i tell to phpunit to use :memory: for certain test class and not for all classes ?
Unfortunately, PHPUnit is now unable to use custom environments for only some test suites. So you can't use the following code:
...
<testsuite name="Application Test Suite">
<directory suffix="Test.php">./tests</directory>
<php>
<env name="DB_DATABASE" value="example_db"/>
</php>
</testsuite>
...
So instead of setting the env DB_DATABASE via the phpunit.xml file, you can set it via the new .env file. Suppose you create a .env.first file that contains:
DB_DATABASE=first_db
Then in the phpunit.xml file, you can create a new <testsuite> which you will later target to use with the .env file you have created. As an example:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<testsuites>
<testsuite name="Foo">
<directory prefix="FirstDB" suffix="Test.php">./tests</directory> <!-- Will match all files in `./tests` whose filename contains a FirstDB prefix and a Test.php suffix -->
</testsuite>
<testsuite name="Bar">
<directory prefix="SecondDB" suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value="second_db"/>
</php>
</phpunit>
Then for the next step you can run it with:
php artisan test --env=first --testsuite=Foo
php artisan test --testsuite=Bar

ModelFactory: Error: Call to a member function connection() on null

While trying to populate database using ModelFactory I am coming across this bit of error, I have been looking up since the last six hours, can not seem to fix it.
My Test runs this:
$books = factory('App\Book', 2)->create();
and the error message is this:
There was 1 error:
1) Tests\App\Http\Controllers\BooksControllerTest::testIndexReturnsCollection
Error: Call to a member function connection() on null
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\Model.php:1234
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\Model.php:1200
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\Model.php:1030
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\Model.php:945
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\Model.php:983
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\FactoryBuilder.php:203
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\support\Collection.php:407
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\FactoryBuilder.php:207
D:\Code\Server\htdocs\rlfp.localhost.com\vendor\illuminate\database\Eloquent\FactoryBuilder.php:185
D:\Code\Server\htdocs\rlfp.localhost.com\tests\app\Http\Controllers\BooksControllerTest.php:35
On my bootstrap/app.php I have on line 26 and 28, like so:
$app->withFacades();
$app->withEloquent();
While my phpunit.xml is like so:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/app.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_DATABASE" value="rlp_rlfpsfactory"/>
</php>
</phpunit>
Do I need to put anything else in the php part of phpunit xml file?
After spending one whole day with no luck, thanks to #ChrisSprague I downgraded Lumen to 5.6 and it worked.
Steps:
In composer.json file change
"laravel/lumen-framework": "5.7.*"
to
"laravel/lumen-framework": "5.6.*"
Delete your vendor folder
Do composer install
Run the test again!
If it still does not work, make sure you have correct test database details in your phpunit.xml file
Mine looks like:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/app.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="DB_DATABASE" value="rlp_rlfpsfactory"/> <!-- this is testing database -->
<env name="DB_USERNAME" value="root"/>
<env name="DB_PASSWORD" value=""/>
</php>
</phpunit>

PHPUnit configuring and running a group test [Laravel 5.6]

I have this phpunit.xml with #somegroup:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Feature Tests">
<directory suffix="Test.php">/tests/Feature</directory>
</testsuite>
<testsuite name="Unit Tests">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
</testsuites>
<groups>
<include>
<group>somegroup</group>
</include>
</groups>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
</php>
</phpunit>
Then I have this method with #group tag:
/**
* #group somegroup
*/
public function testStatus()
{
$response = $this->get('/');
$response->assertStatus(200);
}
And then I run test group tag in command line, like this:
vendor\bin\phpunit --group somegroup
And I get this:
No tests executed!
Test command without #group tag works:
vendor\bin\phpunit
What am I doing wrong?
Is it Laravel that does not support #group?

Resources