0

I created a small library that requires the user to set up a secret constant in order for it to work.

Here is a part of my code:

if (!defined('SOMELIB_SECRET')) {
    throw new RuntimeException('You need to define the constant SOMELIB_SECRET to use this library');
}

This code works great, but I don't know how to test the exception throw. I can test everything if I create the constant in phpunit.xml:

<php>
    <const name="SOMELIB_SECRET" value="ThisIsTheSecretForTests" />
</php>

I can test the exception if I don't add the constant in the PHP.

What I want to do is test both, I would need a way to unset the constant mid-way, which is not really a thing (turns out constants are... constant).

I tried to create 2 test files: 001_SomeLibWithoutSecretTest.php and 002_SomeLibWithSecretTest.php, so that I can create the constant between them. It worked on Linux, but now that I'm using Windows, the tests are called the other way around. Besides, it's a bit hacky: tests should not have to be called in a given order.

After all this introduction, here is my simple question:

How can I run tests, with PHPUnit, defining constants for some tests but not for all?

SteeveDroz
  • 6,006
  • 6
  • 33
  • 65

1 Answers1

2

Here are some ideas:

  1. Enable process isolation
    When processIsolation is enabled, each test will be run in an isolated process. You have to remove your constant from the configuration and define it in setUp, setUpBeforeClass or directly in the tests where you need it.

  2. runkit extension
    The runkit pecl extension has a function to remove an already defined constant. Your tests will depend on that extension, though, which isn't that nice.

  3. Move it somewhere else
    It's usually best when the subject you're testing does not depend on globals. Moving the secret to a configuration object makes it easier to test and harder for the user to forget to configure a required setting.

Philip Weinke
  • 1,804
  • 1
  • 8
  • 13
  • Thank you, it works! For all those reading that question after me, I put `define('SOMELIB_SECRET', 'ThisIsTheSecretForTests');` in the `setUp()` of one class and used `processIsolation`. Downside: it slows down the tests drastically, so be prepare to multiply your tesing time (x25 for me). – SteeveDroz Dec 14 '20 at 15:11
  • As for the other solutions, I'm not fond of #2 (apparently same goes for you) and I agree that #3 would be perfect. Unfortunately, other reasons force me to stick with the constant. I'll keep that in mind, though! – SteeveDroz Dec 14 '20 at 15:13