问题
Unfortunately config(['key' => 'newValue'])
doesn't work in a Dusk setup (for overriding a config value), presumably because it would change the config of the system running the test rather than the experience of the headless browser that gets opened to execute the flow.
And sometimes I can see no way around needing to temporarily change an env value for a certain Dusk test.
E.g. temporarily set QUEUE_DRIVER=sync
when usually it is 'dusk-connection', but in one particular test, I need to check for values in the 'jobs' tables in the DB.
Before upgrading to Laravel >=5.8 (and therefore newer versions of DotEnv), I was able to use this function called within a Dusk test before $this->browse(...
:
/**
* Overrides any .env variables for Dusk tests. https://laracasts.com/discuss/channels/testing/how-to-change-env-variable-config-in-dusk-test
* The changes exist only for that one test because of tearDown.
* Remember that you need to be using `php artisan dusk` instead of `phpunit`.
* https://stackoverflow.com/questions/54407784/laravel-dusk-how-to-change-config-values-before-each-test-for-the-browser#comment103224655_54407784
*
* @param array $variables
*/
protected function overrideDuskEnv($variables = []) {
$path = self::DOT_ENV;
if (file_exists($path)) {
$contentToPrepend = '';
foreach ($variables as $key => $value) {// Convert all new parameters to expected format
$contentToPrepend .= $key . '="' . $value . '"' . PHP_EOL;
}
$originalFileContents = $this->envContents;
$comment = '# ==============================================' . PHP_EOL . '# VARIABLES ABOVE THIS LINE are from "' . __FUNCTION__ . '" function in DuskTestCase ( https://laracasts.com/discuss/channels/testing/how-to-change-env-variable-config-in-dusk-test )' . PHP_EOL;
file_put_contents($path, $contentToPrepend . $comment . $originalFileContents); //"If they are appended, it doesn't seem to take priority."
} else {
throw new \Exception('Could not find env file to override!');
}
}
I was able to call it like this: $this->overrideDuskEnv(['QUEUE_DRIVER' => 'sync']);
But in more recent Laravel versions, environment variables are immutable (see "Read-Only env Helper").
How can I achieve my goal, where Dusk uses .env.dusk.local
for most tests but then for certain tests may differ slightly?
回答1:
Finally after struggling with this problem for 10+ hours, I have a solution.
/**
* @param array $variables
*/
protected function overrideDuskEnv($variables = []) {
$path = self::DOT_ENV;
if (file_exists($path)) {
$contentToAppend = '';
foreach ($variables as $key => $value) {// Convert all new parameters to expected format
$contentToAppend .= $key . '="' . $value . '"' . PHP_EOL;
}
$originalFileContents = $this->envContents;
$comment = '# ==============================================' . PHP_EOL . '# VARIABLES BELOW THIS LINE are from "' . __FUNCTION__ . '" function in DuskTestCase ( https://laracasts.com/discuss/channels/testing/how-to-change-env-variable-config-in-dusk-test )' . PHP_EOL;
$this->baseCommand->consoleOutput('Appending to ' . $path . ': ' . $contentToAppend);
file_put_contents($path, $originalFileContents . $comment . $contentToAppend); //It used to be the case that "If they are appended [rather than prepended], it doesn't seem to take priority", but after the DotEnv upgrade in Laravel 5.8, it seems prepending doesn't work and appending does.
} else {
throw new \Exception('Could not find env file to override!');
}
}
Then in my setUp()
function in my Dusk test class, I call:
$this->overrideDuskEnv([
'SIGNUP_FORM_POST_PATH' => \App\Helpers\Routes::SIGNUP,
'QUEUE_DRIVER' => \App\Helpers\ConfigConstants::DUSK_CONNECTION
]);
Then in each test function after the closing of $this->browse(function (Browser $browser)...
and before assertions, I call:
config(['queue.default' => \App\Helpers\ConfigConstants::DUSK_CONNECTION]); //this does not affect the headless browser but IS probably necessary here so that assertQueued knows to pull from the queue that the headless browser was using.
The tricky part to understand with Dusk is that the environment variables (and therefore the config arrays) of the console process running the tests differ from those that get used by the headless browser (simulating what a real user would experience).
By the way, I had been so hopeful about approaches like this one, but they turned out to be complete wastes of time because DuskCommand is already calling overload to make the env variables mutable.
来源:https://stackoverflow.com/questions/58450836/how-to-override-env-variables-in-laravel-dusk