What are you really trying to do?
Run the time-skipping test suite from inside a Docker container that already has TEMPORAL_ADDRESS=temporal:7233 baked into the
runtime environment (because the same container image runs both the prod app and the tests).
Describe the bug
The official testing-suite docs (https://docs.temporal.io/develop/php/testing-suite) recommend setting TEMPORAL_ADDRESS in
phpunit.xml:
<env name="TEMPORAL_ADDRESS" value="127.0.0.1:7233"/>
This silently does nothing when the variable is already set in the OS environment. PHPUnit's directive is non-overriding by
default — it only sets the value if the var doesn't exist. The fix in PHPUnit is force="true":
<env name="TEMPORAL_ADDRESS" value="127.0.0.1:7233" force="true"/>
But even force="true" only writes to $_ENV / $_SERVER, not to the OS env that \getenv() reads. Quoting the PHP manual:
_ getenv() retrieves environment variables. By default, it queries the OS environment, not $ENV.
Temporal\Testing\WorkflowTestCase::setUp() calls \getenv('TEMPORAL_ADDRESS'):
$temporalAddress = \getenv('TEMPORAL_ADDRESS') ?: '127.0.0.1:7233';
$this->workflowClient = new WorkflowClient(ServiceClient::create($temporalAddress));
So in any environment where TEMPORAL_ADDRESS is already set in OS env (CI runners, Docker containers built from the prod image,
hosted dev environments) — the test client connects to whatever production-style address is baked in, not the in-process test
server.
Symptom
Every workflow start times out at withWorkflowExecutionTimeout with WorkflowFailedException retryState=3. The error message gives no
hint about address mismatch — users assume their workflow logic is broken, the worker isn't registered, or task-queue routing is
wrong. Debugging takes hours.
Diagnostic that would have saved us hours
While a hung test is running, in another shell:
temporal workflow show --address 127.0.0.1:7233 -w <workflowId-from-failure>
"Execution not found in mutable state"
Means the client wrote to a different server. There is currently no log line, no warning, no health-check from WorkflowTestCase that
would surface this.
Workaround
In the test bootstrap, before any SDK code loads:
\putenv('TEMPORAL_ADDRESS=127.0.0.1:7233');
$_ENV['TEMPORAL_ADDRESS'] = '127.0.0.1:7233';
$_SERVER['TEMPORAL_ADDRESS'] = '127.0.0.1:7233';
All three channels are needed because different SDK code paths read different sources.
Suggested Fixes (in order of preference)
- Auto-detect and warn on mismatch. When WorkflowTestCase::setUp() resolves TEMPORAL_ADDRESS, if a test server is running on
127.0.0.1 but getenv() points elsewhere, log a loud warning. Or: if Environment::startTemporalTestServer() was just called by the
bootstrap, force the client to that address.
- Document the gotcha. Add to the testing-suite docs: a section called "Running tests in containers where TEMPORAL_ADDRESS is
pre-set" with the three-channel putenv workaround. Right now docs assume a clean shell environment.
- Have WorkflowTestCase accept an explicit address. Allow protected string $testServerAddress = '127.0.0.1:7233'; override on the
test class, bypassing env resolution entirely. Same shape as Java's TestWorkflowEnvironment.newInstance().
Versions
- temporal/sdk 2.17
- PHP 8.4
- PHPUnit 10.x
- Linux, x86_64
- Reproduced inside Docker (image inherits TEMPORAL_ADDRESS=temporal:7233 from docker-compose.yml).
Related
This is an instance of a broader story — testing-suite docs assume a "clean room" environment. Combined with LINK, the whole
WorkflowTestCase user experience needs a documentation pass for production-realistic setups.
What are you really trying to do?
Run the time-skipping test suite from inside a Docker container that already has TEMPORAL_ADDRESS=temporal:7233 baked into the
runtime environment (because the same container image runs both the prod app and the tests).
Describe the bug
The official testing-suite docs (https://docs.temporal.io/develop/php/testing-suite) recommend setting TEMPORAL_ADDRESS in
phpunit.xml:
<env name="TEMPORAL_ADDRESS" value="127.0.0.1:7233"/>This silently does nothing when the variable is already set in the OS environment. PHPUnit's directive is non-overriding by
default — it only sets the value if the var doesn't exist. The fix in PHPUnit is force="true":
<env name="TEMPORAL_ADDRESS" value="127.0.0.1:7233" force="true"/>But even
force="true"only writes to$_ENV / $_SERVER,not to the OS env that\getenv()reads. Quoting the PHP manual:_ getenv() retrieves environment variables. By default, it queries the OS environment, not $ENV.
Temporal\Testing\WorkflowTestCase::setUp() calls \getenv('TEMPORAL_ADDRESS'):So in any environment where TEMPORAL_ADDRESS is already set in OS env (CI runners, Docker containers built from the prod image,
hosted dev environments) — the test client connects to whatever production-style address is baked in, not the in-process test
server.
Symptom
Every workflow start times out at withWorkflowExecutionTimeout with WorkflowFailedException retryState=3. The error message gives no
hint about address mismatch — users assume their workflow logic is broken, the worker isn't registered, or task-queue routing is
wrong. Debugging takes hours.
Diagnostic that would have saved us hours
While a hung test is running, in another shell:
temporal workflow show --address 127.0.0.1:7233 -w <workflowId-from-failure>"Execution not found in mutable state"
Means the client wrote to a different server. There is currently no log line, no warning, no health-check from WorkflowTestCase that
would surface this.
Workaround
In the test bootstrap, before any SDK code loads:
All three channels are needed because different SDK code paths read different sources.
Suggested Fixes (in order of preference)
127.0.0.1 but getenv() points elsewhere, log a loud warning. Or: if Environment::startTemporalTestServer() was just called by the
bootstrap, force the client to that address.
pre-set" with the three-channel putenv workaround. Right now docs assume a clean shell environment.
test class, bypassing env resolution entirely. Same shape as Java's TestWorkflowEnvironment.newInstance().
Versions
Related
This is an instance of a broader story — testing-suite docs assume a "clean room" environment. Combined with LINK, the whole
WorkflowTestCase user experience needs a documentation pass for production-realistic setups.