Skip to content

Commit

Permalink
API Add withConfig method (#9011)
Browse files Browse the repository at this point in the history
* With config functionality added.
* Update docs/en/02_Developer_Guides/04_Configuration/00_Configuration.md
  • Loading branch information
mfendeksilverstripe authored and Maxime Rainville committed Oct 31, 2019
1 parent d814158 commit e2bea6b
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 1 deletion.
42 changes: 42 additions & 0 deletions docs/en/02_Developer_Guides/04_Configuration/00_Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,48 @@ When you have more than one rule for a nested fragment, they're joined like
That is, the fragment will be included if all Only rules match, except if all Except rules match.
</div>

## Unit tests

Sometimes, it's necessary to change a configuration value in your unit tests.
One way to do this is to use the `withConfig` method.
This is especially handy when using data providers.
Example below shows one unit test using a data provider.
This unit test changes configuration before testing functionality.
The test will run three times, each run with different configuration value.
Note that the configuration change is active only within the callback function.

```php
/**
* @dataProvider testValuesProvider
* @param string $value
* @param string $expected
*/
public function testConfigValues($value, $expected)
{
$result = Config::withConfig(function(MutableConfigCollectionInterface $config) use ($value) {
// update your config
$config->set(MyService::class, 'some_setting', $value);
// your test code goes here and it runs with your changed config
return MyService::singleton()->executeSomeFunction();
});
// your config change no longer applies here as it's outside of callback
// assertions can be done here but also inside the callback function
$this->assertEquals($expected, $result);
}
public function testValuesProvider(): array
{
return [
['test value 1', 'expected value 1'],
['test value 2', 'expected value 2'],
['test value 3', 'expected value 3'],
];
}
```

## API Documentation

* [Config](api:SilverStripe\Core\Config\Config)
Expand Down
20 changes: 19 additions & 1 deletion src/Core/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use InvalidArgumentException;
use SilverStripe\Config\Collections\ConfigCollectionInterface;
use SilverStripe\Config\Collections\DeltaConfigCollection;
use SilverStripe\Config\Collections\MutableConfigCollectionInterface;

abstract class Config
Expand Down Expand Up @@ -119,4 +118,23 @@ public static function forClass($class)
{
return new Config_ForClass($class);
}

/**
* Perform the given operation in an isolated config state.
* On return, the config state will be restored, so any modifications are temporary.
*
* @param callable $callback Callback to run. Will be passed the nested config state as a parameter
* @return mixed Result of callback
*/
public static function withConfig($callback)
{
static::nest();
$config = static::modify();

try {
return $callback($config);
} finally {
static::unnest();
}
}
}
41 changes: 41 additions & 0 deletions tests/php/Core/Config/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace SilverStripe\Core\Tests\Config;

use SilverStripe\Config\Collections\MutableConfigCollectionInterface;
use SilverStripe\Config\MergeStrategy\Priority;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
Expand Down Expand Up @@ -322,4 +323,44 @@ public function testForClass()
$this->assertTrue(empty($config->bar));
$this->assertNull($config->bar);
}

public function testWithConfig()
{
$oldValue = 'test_1';
$newValue1 = 'new value 1';
$newValue2 = 'new value 2';
$property = 'third';

$this->assertEquals(
$oldValue,
Config::inst()->get(ConfigTest\First::class, $property)
);

Config::withConfig(function (MutableConfigCollectionInterface $config) use ($newValue1, $newValue2, $property) {
$config->set(ConfigTest\First::class, $property, $newValue1);

$this->assertEquals(
$newValue1,
Config::inst()->get(ConfigTest\First::class, $property)
);

$resultValue = Config::withConfig(function (MutableConfigCollectionInterface $config) use ($newValue2, $property) {
$config->set(ConfigTest\First::class, $property, $newValue2);

return Config::inst()->get(ConfigTest\First::class, $property);
});

$this->assertEquals($newValue2, $resultValue);

$this->assertEquals(
$newValue1,
Config::inst()->get(ConfigTest\First::class, $property)
);
});

$this->assertEquals(
$oldValue,
Config::inst()->get(ConfigTest\First::class, $property)
);
}
}

0 comments on commit e2bea6b

Please sign in to comment.