Phpunit overriding variable in .env - php

In my .env file of a laravel 5.1 project i have set the APP_ENV to local, But when i run the test from the terminal the with
vendor/bin/phpunit
the debug and die on
dd(env(APP_ENV));
gives me "testing".
I Have dont a good research on this, tried using the following ways -
trying to set the APP_ENV=local pipelining vendor/bin/phpunit form the cli.
Trying to add env variable in the phpunit.xml file<env name="APP_ENV" value="local" override="true"> (dosent seem to override though)
adding a .env.testing file and setting the APP_ENV=local
in the testCase.php file where the application autoloads $app->loadEnvironmentFrom('.env.testing');
none of the above methods give me the expected result rather everytime i run the test give APP_ENV as "testing".
Not able to trace where is phpunit setting this variable from.
Pls help out!

In vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php search for putenv('APP_ENV=testing'); try to change this to local.
This should work for you, though it is not advisable.

Related

.env files in Github Actions CI/CD workflows: how to provide these into the workflow

I use Github Actions workflows for my CI/CD processes for Node and PHP projects.
Within a workflow I clone my repository into Github Actions runner virtual machine. Then in order to run tests within a workflow I have to have the .env file in the cloned repository.
The problem is my .env file is not a part of repository (which is the ubuquitous practice).
To solve the problem I use what I consider a workaround: set up MY_PROJECT_ENV Github Action sercret variable, manually put there the content of my .env file and then dynamically create the .env file within my workflow with Linux console echo "${{ secrets.MY_PROJECT_ENV}}" > .env. This works.
But I would like to know are there other approaches for providing .env files to Github Actions workflows?
There are 3 ways to do this I know by now. I put the answer to my own question a year after in the different question. See there.
For the sake of SO rules and findablity I put here a summary.
You keep your .env file in the repository. Use dotenv actions to read your file into the workflow.
You keep the file out of the repository. Then you have 2 ways of getting .env variables:
2.1. as I wrote in my question above manually copy the file content to the GitHub actions secret variable and then in your workflow create the .env file from that variable.
2.2. Use the GitHub Actions API to create/update the secrets: write the NodeJS script on your machine (chances are you anyway use Webpack, Gulp or the like Node thing so you have Node installed).
The script should read the local .env files and write their content to the GH secrets. Of course you can write a custom console utilty to do this with any language you use in your project.
As easy as this :)
As you know .env doesn't mean to push to the remote repository.
You need to somehow add the environment variables to the machine that you're running the program.
In your case, you can add environment variables by using the .yaml file as below
steps:
- name: Hello Program
run: Hello $FIRST_NAME $LAST_NAME!
env:
FIRST_NAME: Akhil
LAST_NAME: Pentamsetti
for more information please visit github official doc about using the environment variables.
I do the following, which is simple and effective:
Add environment variables (either define them in the yaml file or as secrets) as needed
Keep .env.example in the repository, and run the following at the start of the CI job:
# Create the .env file
cp .env.example .env
# Install dependencies so we can run artisan commands
composer install ...
# generate an APP_KEY
php artisan key:generate
An alternative to this is to commit a .env.ci file to the repository with env vars specific to the CI environment, and run cp .env.ci .env when running tests. Sensitive keys should still be set as secrets.
You can technically provide all of your env vars between secrets / env's in the YAML file and have no .env file, but I like having a random APP_KEY set per test run to ensure there's nothing relying on a specific APP_KEY.
Environment Precedence
As an aside, here's how environment precedence works with Laravel in phpunit tests. This is laravel specific and may come at a surprise as it's not exactly how phpunit alone works outside of Laravel:
Env vars set in phpunit.xml always "win" (this is true in Laravel despite what phpunit's docs say about system env vars taking precedence over phpunit.xml file items)
System environment variations (in GitHub actions, these are ones set as an env var when running commands in the yaml file)
.env file items
Source: I created/run Chipper CI, a CI platform for Laravel.

Laravel not reading env variables from different env files

After upgrade from 5.0 to 5.8, laravel stopped reading env variables if the env is different than .env file.
For example, if i have .env file with the USE_SSL=true inside it.
env('USE_SSL') will be true
But if i have .env file pointing to another env:
APP_ENV=dev
and than i'll have .env.dev file containing USE_SSL=true , env('USE_SSL') will be null.
I tried composer dump-autoload and php artisan config:clear, and php artisan config:cache - no luck. cached or not, i can't get the value.
I tried naming the files .dev.env and .env.dev - no luck.
Any ideas would be appreciated.
I'm adding this as an answer, but please note this isn't how .env file should be used according to laravel docs. It's just a way i needed to use due to some restrictions which required me to use different config files for each env, and load it in runtime. For correct usage of .env file check the docs.
This is a way of loading different config files in runtime depends on where the APP_ENV is pointing. I'm marking this as answered since it's answering this specific question.
.env
APP_ENV=specific_domain
.env.specific_domain
USE_SSL=true
Http/Kernel.php
public function __construct(Application $app, Router $router)
{
parent::__construct($app, $router);
$app_env = explode("=", file($app->environmentFilePath(), FILE_IGNORE_NEW_LINES)[0])[1];
$app->loadEnvironmentFrom(".env.$app_env");
}
Alright if you really wanted to do this,
Route::get('renderEnvChaining',function(){
$myCustomEnv = parse_ini_file(base_path(env('CUSTOM_ENV')));
return $myCustomEnv['USE_SSL']; // This will return true
});
In my .env file i've mentioned this,
CUSTOM_ENV=.env.example
Now i in default env.example i put this
USE_SSL="true" // This will return true
USE_SSL=true // This will return 1
I just found that .ini and .env follows the same values, so i parsed .env file as .ini file,
Give this a try, i've never done this thing before, please concern with other developers before running this into production server

Laravel 5.4 phpunit vs dusk tests Env App_Url

PHPunit tests and Artisan Dusk tests both use APP_URL from .env File.
But there is something strange, maybe because of my setup but I do not know, it insane.
I have Xampp, my project is on localhost/forum/
When I have
APP_URL=http://localhost
My unit tests are OK.
e.g.
$response = $this->get('sekcja/sadsadsadsadas');
$response->assertStatus(200);
All good.
Like laravel knows it is http://localhost but tests on http://localhost/forum/ because there is this project and looks on http://localhost/forum/sekcja/sadsadsadsadas
But...
Dusk see this wrong.
Dusk is loading me localhost where is welcome XAMPP's Page.
Not my project page at localhost/forum/
Then I change in ENV to APP_URL=http://localhost/forum/
And works good, dusk test are good...
But then, you know what?
My PHPunit tests aren't good, they doesn't work anymore.
They can't find this $this->get('sekcja/sadsadsadsadas'); anymore.
So my question is
What is happening here? In documentation I read for dusk i have to set this as I have set, but them my PHPunit test are broken. Why? if both phpunit and dusk test are using the same variable why they want different value for it? That's kinda silly.
You can create a seperate .env file for dusk specifically.
As stated in the docs:
When running tests, Dusk will back-up your .env file and rename your
Dusk environment to .env. Once the tests have completed, your .env
file will be restored.
This should help you fix your problem.
https://laravel.com/docs/5.4/dusk/#environment-handling

Laravel Lumen Memcached not found

Ok, I just started with Lumen and I'm trying to use the Auth, but a call to either Auth::check or any other function of Auth.. leads to the below Error
Fatal error: Class 'Memcached' not found in vendor\illuminate\cache\MemcachedConnector.php on line 52.
I don't want to use Memcached never used it before.
I disabled it in the .env file and set the CACHE_DRIVER and SESSION_DRIVER to array, but still shows the same error.
I decided not to use Auth again and to manually handle my authetication with sessions/tokens, but enabling the MiddleWare StartSession results to the same error.
$app->middleware([
// 'Illuminate\Cookie\Middleware\EncryptCookies',
// 'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
// 'Illuminate\View\Middleware\ShareErrorsFromSession',
// 'Laravel\Lumen\Http\Middleware\VerifyCsrfToken',
]);
Please I'd be so glad if anyone can really help me out here
EDIT
After going A little Deep in the framework
I Hard Coded the session driver name in the SessionManager Class
within the method getSessionConfig
public function getSessionConfig()
{
$this->setDefaultDriver("cookie");//I added this line
return $this->app['config']['session'];
}
It works though but not a good way of doing things.
There is no config file, i believe all configurations are written in .env file, but i really don't know why the session_driver and cache_driver is defaulted to memecached even after changing it in the .env and then ran composer dump-autoload ... Lumen :(
EDIT
This is my .env file
APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomKey!!!
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=
CACHE_DRIVER=array
SESSION_DRIVER=cookie
QUEUE_DRIVER=database
I already have this line uncommented in my bootsrap/app.php
Dotenv::load(__DIR__.'/../');
My DataBase configuration works perfectly so the .env file is loaded
quite alright.
I spent 3 hours on this problem today. With the help of the post of demve in this topic, I found the solution. Very simple! I hope it won't affect me later in my development.
Just to it, in the .env file :
CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=array
Ok, I make an UPDATE because I was faced with a new problem about the session. In fact, when you set the previous parameters, your session won't be persistent, like said in the documentation: array - sessions will be stored in a simple PHP array and will not be persisted across requests.
So I have to change it, always in .env a file like that :
SESSION_DRIVER=cookie
With a var_dump(Session::all()); I now can see the whole values of my session
You may need to restart your server, especially if you're using php artisan serve.
Lumen doesn't appear to pick up .env changes per-request.
I had exactly the same issue - trying to use file cache, but received errors regarding Memcached - restarting the server reloads the .env file.
This issue resolved when i installed this package so try at least
First i tried this and it works fine
CACHE_DRIVER = array
but then thought about what is memcached
Then i tried this and it works fine without changing driver memcached
apt-get install php-memcached
yum package manager or in Amazon Linux.
yum install php-memcached -y
In .env file replace
#This line:-
CACHE_DRIVER = memcached
#With this:-
CACHE_DRIVER = array
Make sure not to get caught out by your .env file not being loaded, which by default it's commented out in Lumen. So if you are specifying a different cache driver in your .env, do the following.
Note: If you are using the .env file to configure your application, don't forget to uncomment the Dotenv::load() method in your bootstrap/app.php file.
Source: http://lumen.laravel.com/docs/cache
in your .env file, you can also use CACHE_DRIVER=file instead of CACHE_DRIVER=memcached
In my case i added Add CACHE_DRIVER=array in .env file
Then
Dotenv::load(__DIR__.'/../');
in my bootstrap/app.php and the .env file started working.
For me, the issue was that I used the php-7 branch of homestead repository which does not have PHP memcached ready.
I had a similar problem now, I couldn't track it down but my guess is that it has something to do with the fact that the defaults configurations are stored in the vendor/laravel/lumen-framework/config folder, the DotEnv::$inmutable setting and the artisan serveserver.
The solution that worked for me was:
Add in bootstrap/app.php the following:
Dotenv::makeMutable();
Dotenv::load(__DIR__.'/../');
Dotenv::makeImmutable();
in the .env file, set all the configuration to "basic drivers" (array, file) even if you are not going to use them, because you w
If you have a new lumen installation,
you must rename .env.example to .env . So it can read your configurations!
This happens if your .env file is owned by another user than the one trying to run the artisan command.
Check if memcached is installed, if not install it by running:
apt-get install php5-memcached

Laravel phpunit not getting right url

I've changed the app.url config value to the correct url (http://testing.local) for testing locally, however when I run my phpunit tests and try to call(), it is trying to query http://localhost instead of the value of app.url. What do I need to do to get phpunit to call the right path?
I know that it is not actually calling the url, just processing it as if it was, but I can't seem to get it to actually work. Could it have something to do with testing.local directly linking to /public instead of /?
If you want to statically specify a root URL for your tests, add this to phpunit.xml:
<env name="APP_URL" value="http://testing.local"/>
Instead, if you want to change the URL dinamically during your tests, from Laravel 5.4 the $baseUrl method doesn't work anymore.
Also, trying to set the url dinamically with \Config:set('app.url', 'http://testing.local') doesn't work either, as it seems that Laravel caches the root url
You can set dynamically a custom URL with:
\URL::forceRootUrl('http://testing.local');
To change testing url of PHPUnit:
Go to /tests/TestCase.php in your Laravel project.
Change next line to url you need:
// The base URL to use while testing the application.
protected $baseUrl = 'http://newurl.com';
Done.
As stated above, you can use Config::get('app.url') anywhere in your laravel code, including your unit-test.
Note: it is recommended to set this value in your .env file so that it can be set specifically for each environment.
When working with config and .env variables, remember to clear the cache for these with the following commands:
php artisan cache:clear
php artisan config:cache
Laravel has a few functions to get url: (1) url()->current() (2) request()->url()
Both of them are using the same source.
In case of phpunit, tests are setting data there from the config
config('app.url')
and config is getting data from .env record APP_URL.
So you have a few options
1)
to set APP_URL in .env file or in phpunit.xml file - in both cases, a the value is only used in unit tests.
BUT you would have only one URL for all your unit tests.
2)
set APP_URL in runtime
but, you need to do it before function setUp() in Tests\TestCase
public function setUp(): void
{
$_ENV['APP_URL'] = 'example.com';
parent::setUp();
}
Because all the initialisation is hidden in setUp function you CANNOT use
config()->set('app.url',.... Before parent::setUp(); would be too early, and after it - would be too late.
BUT you would have only one URL per unit test file.
3)
request()->headers->set('HOST', 'example.com');
you can set it anywhere after setUp() function and it will overwrite .env and config()
No 'BUTs'.
I think the best way is to set the test app url in phpunit.xml configuration file:
<env name="APP_URL" value="some-url.test"/>
To the best of my understanding, Laravel is supposed to use the 'testing' environment variables when you run PHPUnit. However, I am having the same issue that you are. To get it to work I manually set the app url.
$test_url = Config::get('app.url');
Hope this helps anyone who comes across the same issue.

Categories