I have unit and kernel tests that check for the existence of secrets (via define
) in a settings.secrets.php file in my local site (Acquia Cloud convention). This file is not committed to the repo, stored in the database or exported.
When writing a functional test, I ran into an issue (which sounds similar to this one). If I tried to put define
in my test file, I would just get an error and test failure saying the constant is undefined.
I came up with this, overriding prepareSettings()
to write to the settings file generated for functional tests:
/**
* {@inheritdoc}
*/
protected function prepareSettings() {
parent::prepareSettings();
$directory = DRUPAL_ROOT . '/' . $this->siteDirectory;
copy(DRUPAL_ROOT . '/sites/example.secrets.settings.php', $directory . '/secrets.settings.php');
$append_line = 'include_once dirname(__FILE__) . \'/secrets.settings.php\';';
file_put_contents($directory . '/settings.php', $append_line, FILE_APPEND);
}
The file that is copied just contains define
statements with fake values.
Is this a valid approach to fixing this problem in a functional test, or did I miss something else and don't need the above code?
Update:
The code in the question only works for Functional tests as they have that method. Lower level kernel and unit tests have no access to that.
Instead, I found that you can add constants to phpunit.xml and then the tests have them defined:
<php>
<const name="MYMODULE_API_URL" value="https://api.myproject.localhost"/>
<const name="MYMODULE_API_KEY" value="123456789"/>
<!-- Set error reporting to E_ALL. -->
<ini name="error_reporting" value="32767"/>
There appears to be one exception though - BrowserTests that have calls to drupalGet
can still throw Use of undefined constant
exception and fail the test. I can't figure that part out. I also tried using a testing profile that does not enable page or dynamic cache - same result. For now I had to comment out the drupalGet calls until I figure it out later.
However by adding it to phpunit.xml, you cannot do it in prepareSettings
or you get a 'constant already defined'. So it appears that it is aware of the existing of this value.
Why do non BrowserTests not adhere to constants that are set either in code or in phpunit.xml, but any other tests do?
Update 2:
Here is the code in the test. The lines in the first loop for drupalGet
will fail with the error, but curiously, the last block passes just fine:
foreach ($permitted as $account) {
$this->drupalLogin($account);
foreach ($this->entity_types as $entity_type) {
$this->drupalGet('node/' . $entity_type['nid'] . '/edit');
if ($entity_type['response'] === 200) {
$this->assertLinkByHref('/node/' . $entity_type['nid'] . '/update');
$this->assertLinkByHref('/node/' . $entity_type['nid'] . '/data');
} else {
$this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/update');
$this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/data');
}
$this->drupalGet('/node/' . $entity_type['nid'] . '/update');
$this->assertResponse($entity_type['response']);
$this->drupalGet('/node/' . $entity_type['nid'] . '/data');
$this->assertResponse($entity_type['response']);
}
$this->drupalLogout();
}
// As someone without the specific permission
$this->drupalLogin($this->staff);
foreach ($this->entity_types as $entity_type) {
$this->drupalGet('node/' . $entity_type['nid'] . '/edit');
$this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/update');
$this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/data');
$this->drupalGet('/node/' . $entity_type['nid'] . '/update');
$this->assertResponse(403);
$this->drupalGet('/node/' . $entity_type['nid'] . '/data');
$this->assertResponse(403);
}