Is it possible to mock the application's environment?
I have a piece of middleware (in Lumen) that looks like this:
if ((app()->environment('production') && $request_mode != 'production') ||
(! app()->environment('production') && $request_mode != 'development'))
{
throw new MismatchedModeException();
}
This is an extra layer of protection (beyond an API token for authentication and an IP whitelist -- we're thorough) to make sure that a specific request mode is used based on the environment that receives the request.
The problem I have is that when running tests on the project, the environment is always 'testing', making it impossible for me to accurately test this middleware for proper handling of 'production' requests.
I have tried a number of methods that have all failed:
PHPUnit::createMock(Application::class, ['environment']) -- Mocked 'environment()' calls fail to use mocked responses (tried many variations of will() and willReturn())
Instantiation of "mini-app" inside test -- didn't allow us to do anything we couldn't do on the full app itself.
putenv('APP_ENV=production') -- seems to be the most direct, but it stalls phpunit when using expectException()
I figure I can't be the first person to have something like this, so I'm reaching to see if anyone else has successfully accomplished what I'm trying to do.
Here's an example test method that attempts to make sure the exception is thrown when someone sends a 'development' request to the 'production' environment:
public function testInvalidDevelopmentMode()
{
// fake production environment
putenv('APP_ENV=production');
$request = new Request();
$request->headers->add([
'mode' => 'development'
]);
$next = function($val) {
return $val;
};
$this->expectException(MismatchedModeException::class);
$response = (new RequestModeMiddleware)->handle(
$request, $next, 'testEndpoint'
);
/* phpunit hangs here after the exception is logged to lumen.log */
// restore testing environment
putenv('APP_ENV=testing');
}