WordPress function gives different results outside vs inside PHPUnit test

The reason this is happening is actually not because of anything in the code you’ve posted, per se, but because of how you have PHPUnit configured. The shortcode callbacks are stored in a global ($shortcode_tags). When you load WP, the shortcode is registered and added to the global. You call shortcode_exists(), it checks $shortcode_tags, and returns true. Then PHPUnit starts running your tests. And it clears out the global variable scope. So, when your test is run, $shortcode_tags no longer exists, so shortcode_exists() reports that your shortcode isn’t registered. (PHPUnit will then restore the global scope to what it was before the test, so that tests don’t affect the global variables. Running shortcode_exists() after the tests are finished would report true.)

PHPUnit does have the backupGlobals setting, and setting it to false will prevent PHPUnit from touching the global scope. And that should fix your issues. However….

A more excellent way

As the author of this tutorial, I would like to recommend that you set up your tests more like I show there. The reason being that you won’t have to write all this bootstrap to get PHPUnit to play with WordPress. You should instead just use WordPress’s PHPUnit bootstrap, which, obviously, is already engineered to play nice with WordPress. 🙂