Functional tests report constants are undefined, even if the constant is set in the test or phpunit.xml
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, and thus, they would fail.

Instead, I found that you can add constants to phpunit.xml and then the tests have them defined:

    &lt;php&gt;
        &lt;const name="MYMODULE_API_URL" value="https://api.myproject.localhost"/&gt;
        &lt;const name="MYMODULE_API_KEY" value="123456789"/&gt;
        &lt;!-- Set error reporting to E_ALL. --&gt;
        &lt;ini name="error_reporting" value="32767"/&gt;


Then you can remove the prepareSettings method from functional tests. However, there seems to be another bug (that I can't track down) where tests that use drupalGet can sometimes fail with an undefined constant error, even though it is defined in the configuration file (you can do it in code too, and will still fail).

My only guess here is that its an issue with a new process spawn not getting the defined configuration from phpunit.xml, or files are loaded out of order (test file constants aren't seen?). 

I settled on the following. I left the constants defined in phpunit.xml so my unit/kernel tests did not need them littered in the tests. For functional tests, I put prepareSettings back in with some changes:

  protected function prepareSettings() {
    parent::prepareSettings();
    $directory = DRUPAL_ROOT . '/' . $this-&gt;siteDirectory;
    copy(DRUPAL_ROOT . '/sites/functional.settings.php', $directory . '/functional.settings.php');
    $append = 'include dirname(__FILE__) . \'/functional.settings.php\';';
    file_put_contents($directory . '/settings.php', $append, FILE_APPEND | LOCK_EX);
  }


The contents of the file:

/**
 * @file
 * Functional tests settings file.
 *
 * There is a weird bug where constants are not recognized in certain cases
 * in functional tests, despite them being defined in phpunit.xml.dist.
 *
 * Functional tests should include any required constants here to avoid this
 * bug.
 *
 * @see https://drupal.stackexchange.com/questions/292713/functional-tests-report-constants-are-undefined-even-if-the-constant-is-set-in
 */

if (!defined('MYMODULE_API_URL')) {
  define('MYMODULE_API_URL', 'https://api.docker.localhost');
}

if (!defined('MYMODULE_API_key')) {
  define('MYMODULE_API_key', 'foobar');
}


Now, with the functional test uncommenting all the calls to drupalGet, all tests are passing with no errors about undefined constants.