silverstripe-framework/tests/php/Core/Injector/InjectorTest.php

1042 lines
34 KiB
PHP
Raw Normal View History

<?php
2016-10-14 03:30:05 +02:00
namespace SilverStripe\Core\Tests\Injector;
use SilverStripe\Core\Config\Config;
2017-03-24 03:50:39 +01:00
use SilverStripe\Core\Injector\Factory;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Injector\InjectorNotFoundException;
use SilverStripe\Core\Injector\SilverStripeServiceConfigurationLocator;
2016-10-14 03:30:05 +02:00
use SilverStripe\Core\Tests\Injector\AopProxyServiceTest\AnotherService;
use SilverStripe\Core\Tests\Injector\AopProxyServiceTest\SampleService;
use SilverStripe\Core\Tests\Injector\InjectorTest\CircularOne;
use SilverStripe\Core\Tests\Injector\InjectorTest\CircularTwo;
use SilverStripe\Core\Tests\Injector\InjectorTest\ConstructableObject;
use SilverStripe\Core\Tests\Injector\InjectorTest\DummyRequirements;
use SilverStripe\Core\Tests\Injector\InjectorTest\EmptyFactory;
2016-10-14 03:30:05 +02:00
use SilverStripe\Core\Tests\Injector\InjectorTest\MyChildClass;
use SilverStripe\Core\Tests\Injector\InjectorTest\MyParentClass;
use SilverStripe\Core\Tests\Injector\InjectorTest\NeedsBothCirculars;
use SilverStripe\Core\Tests\Injector\InjectorTest\NewRequirementsBackend;
use SilverStripe\Core\Tests\Injector\InjectorTest\OriginalRequirementsBackend;
use SilverStripe\Core\Tests\Injector\InjectorTest\OtherTestObject;
use SilverStripe\Core\Tests\Injector\InjectorTest\TestObject;
use SilverStripe\Core\Tests\Injector\InjectorTest\TestSetterInjections;
use SilverStripe\Core\Tests\Injector\InjectorTest\TestStaticInjections;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Dev\TestOnly;
use stdClass;
2016-10-14 03:30:05 +02:00
define('TEST_SERVICES', __DIR__ . '/AopProxyServiceTest');
/**
* Tests for the dependency injector
2014-08-15 08:53:05 +02:00
*
* Note that these are SS conversions of the existing Simpletest unit tests
*
* @author marcus@silverstripe.com.au
* @license BSD License http://silverstripe.org/bsd-license/
2016-10-14 03:30:05 +02:00
* @skipUpgrade
*/
class InjectorTest extends SapphireTest
{
protected $nestingLevel = 0;
protected function setUp(): void
{
parent::setUp();
$this->nestingLevel = 0;
}
protected function tearDown(): void
{
while ($this->nestingLevel > 0) {
$this->nestingLevel--;
Config::unnest();
}
parent::tearDown();
}
public function testCorrectlyInitialised()
{
$injector = Injector::inst();
$this->assertTrue(
$injector->getConfigLocator() instanceof SilverStripeServiceConfigurationLocator,
'Failure most likely because the injector has been referenced BEFORE being initialised in Core.php'
);
}
public function testBasicInjector()
{
$injector = new Injector();
$injector->setAutoScanProperties(true);
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
]
];
$injector->load($config);
$this->assertFalse($injector->has('UnknownService'));
$this->assertNull($injector->getServiceName('UnknownService'));
$this->assertTrue($injector->has('SampleService'));
$this->assertEquals(
'SampleService',
$injector->getServiceName('SampleService')
);
$myObject = new TestObject();
$injector->inject($myObject);
$this->assertInstanceOf(
SampleService::class,
$myObject->sampleService
);
}
public function testEmptyFactory()
{
$this->expectException(InjectorNotFoundException::class);
$injector = new Injector();
$services = [
'SomeClass' => [
'class' => AnotherService::class,
'factory' => EmptyFactory::class,
]
];
$injector->load($services);
$injector->create('SomeClass');
}
public function testConfiguredInjector()
{
$injector = new Injector();
$services = [
'AnotherService' => [
'class' => AnotherService::class,
'src' => TEST_SERVICES . '/AnotherService.php',
'properties' => ['config_property' => 'Value'],
],
'SampleService' => [
'class' => SampleService::class,
'src' => TEST_SERVICES . '/SampleService.php',
]
];
$injector->load($services);
$this->assertTrue($injector->has('SampleService'));
$this->assertEquals(
'SampleService',
$injector->getServiceName('SampleService')
);
// We expect a false because the AnotherService::class is actually
// just a replacement of the SilverStripe\Core\Tests\Injector\AopProxyServiceTest\SampleService
$this->assertTrue($injector->has('SampleService'));
$this->assertEquals(
'AnotherService',
$injector->getServiceName('AnotherService')
);
$item = $injector->get('AnotherService');
$this->assertEquals('Value', $item->config_property);
}
public function testIdToNameMap()
{
$injector = new Injector();
$services = [
'FirstId' => AnotherService::class,
'SecondId' => SampleService::class,
];
$injector->load($services);
$this->assertTrue($injector->has('FirstId'));
$this->assertEquals($injector->getServiceName('FirstId'), 'FirstId');
$this->assertTrue($injector->has('SecondId'));
$this->assertEquals($injector->getServiceName('SecondId'), 'SecondId');
$this->assertTrue($injector->get('FirstId') instanceof AnotherService);
$this->assertTrue($injector->get('SecondId') instanceof SampleService);
}
public function testReplaceService()
{
$injector = new Injector();
$injector->setAutoScanProperties(true);
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
]
];
// load
$injector->load($config);
// inject
$myObject = new TestObject();
$injector->inject($myObject);
$this->assertInstanceOf(
SampleService::class,
$myObject->sampleService
);
// also tests that ID can be the key in the array
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/AnotherService.php',
'class' => AnotherService::class,
]
];
// , 'id' => SampleService::class));
// load
$injector->load($config);
$injector->inject($myObject);
$this->assertInstanceOf(
AnotherService::class,
$myObject->sampleService
);
}
public function testUpdateSpec()
{
$injector = new Injector();
$services = [
AnotherService::class => [
'src' => TEST_SERVICES . '/AnotherService.php',
'properties' => [
'filters' => [
'One',
'Two',
]
],
]
];
$injector->load($services);
$injector->updateSpec(AnotherService::class, 'filters', 'Three');
$another = $injector->get(AnotherService::class);
$this->assertEquals(3, count($another->filters));
$this->assertEquals('Three', $another->filters[2]);
}
public function testConstantUsage()
{
$injector = new Injector();
$services = [
AnotherService::class => [
'properties' => [
'filters' => [
'`BASE_PATH`',
2017-10-09 01:41:34 +02:00
'`TEMP_PATH`',
'`NOT_DEFINED`',
'THIRDPARTY_DIR' // Not back-tick escaped
]
],
]
];
$injector->load($services);
$another = $injector->get(AnotherService::class);
$this->assertEquals(
[
BASE_PATH,
2017-10-09 01:41:34 +02:00
TEMP_PATH,
null,
'THIRDPARTY_DIR',
],
$another->filters
);
}
public function testAutoSetInjector()
{
$injector = new Injector();
$injector->setAutoScanProperties(true);
$injector->addAutoProperty('auto', 'somevalue');
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class
]
];
$injector->load($config);
$this->assertTrue($injector->has('SampleService'));
$this->assertEquals(
'SampleService',
$injector->getServiceName('SampleService')
);
// We expect a false because the AnotherService::class is actually
// just a replacement of the SilverStripe\Core\Tests\Injector\AopProxyServiceTest\SampleService
$myObject = new InjectorTest\TestObject();
$injector->inject($myObject);
$this->assertInstanceOf(
SampleService::class,
$myObject->sampleService
);
$this->assertEquals($myObject->auto, 'somevalue');
}
public function testSettingSpecificProperty()
{
$injector = new Injector();
$config = [AnotherService::class];
$injector->load($config);
$injector->setInjectMapping(TestObject::class, 'sampleService', AnotherService::class);
$testObject = $injector->get(TestObject::class);
$this->assertInstanceOf(
AnotherService::class,
$testObject->sampleService
);
}
public function testSettingSpecificMethod()
{
$injector = new Injector();
$config = [AnotherService::class];
$injector->load($config);
$injector->setInjectMapping(TestObject::class, 'setSomething', AnotherService::class, 'method');
$testObject = $injector->get(TestObject::class);
$this->assertInstanceOf(
AnotherService::class,
$testObject->sampleService
);
}
public function testInjectingScopedService()
{
$injector = new Injector();
$config = [
AnotherService::class,
'SilverStripe\Core\Tests\Injector\AopProxyServiceTest\AnotherService.DottedChild' => SampleService::class,
];
$injector->load($config);
$service = $injector->get('SilverStripe\Core\Tests\Injector\AopProxyServiceTest\AnotherService.DottedChild');
$this->assertInstanceOf(SampleService::class, $service);
$service = $injector->get('SilverStripe\Core\Tests\Injector\AopProxyServiceTest\AnotherService.Subset');
$this->assertInstanceOf(AnotherService::class, $service);
$injector->setInjectMapping(TestObject::class, 'sampleService', 'SilverStripe\Core\Tests\Injector\AopProxyServiceTest\AnotherService.Geronimo');
$testObject = $injector->create(TestObject::class);
$this->assertEquals(get_class($testObject->sampleService), AnotherService::class);
$injector->setInjectMapping(TestObject::class, 'sampleService', 'SilverStripe\Core\Tests\Injector\AopProxyServiceTest\AnotherService.DottedChild.AnotherDown');
$testObject = $injector->create(TestObject::class);
$this->assertEquals(get_class($testObject->sampleService), SampleService::class);
}
public function testInjectUsingConstructor()
{
$injector = new Injector();
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
'constructor' => [
'val1',
'val2',
]
]
];
$injector->load($config);
$sample = $injector->get('SampleService');
$this->assertEquals($sample->constructorVarOne, 'val1');
$this->assertEquals($sample->constructorVarTwo, 'val2');
$injector = new Injector();
$config = [
'AnotherService' => AnotherService::class,
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
'constructor' => [
'val1',
'%$AnotherService',
]
]
];
$injector->load($config);
$sample = $injector->get('SampleService');
$this->assertEquals($sample->constructorVarOne, 'val1');
$this->assertInstanceOf(
AnotherService::class,
$sample->constructorVarTwo
);
$injector = new Injector();
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
'constructor' => [
'val1',
'val2',
]
]
];
$injector->load($config);
$sample = $injector->get('SampleService');
$this->assertEquals($sample->constructorVarOne, 'val1');
$this->assertEquals($sample->constructorVarTwo, 'val2');
// test constructors on prototype
$injector = new Injector();
$config = [
'SampleService' => [
'type' => 'prototype',
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
'constructor' => [
'val1',
'val2',
]
]
];
$injector->load($config);
$sample = $injector->get('SampleService');
$this->assertEquals($sample->constructorVarOne, 'val1');
$this->assertEquals($sample->constructorVarTwo, 'val2');
$again = $injector->get('SampleService');
$this->assertFalse($sample === $again);
$this->assertEquals($sample->constructorVarOne, 'val1');
$this->assertEquals($sample->constructorVarTwo, 'val2');
}
public function testInjectUsingSetter()
{
$injector = new Injector();
$injector->setAutoScanProperties(true);
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
]
];
$injector->load($config);
$this->assertTrue($injector->has('SampleService'));
$this->assertEquals('SampleService', $injector->getServiceName('SampleService'));
$myObject = new InjectorTest\OtherTestObject();
$injector->inject($myObject);
$this->assertInstanceOf(
SampleService::class,
$myObject->s()
);
// and again because it goes down a different code path when setting things
// based on the inject map
$myObject = new InjectorTest\OtherTestObject();
$injector->inject($myObject);
$this->assertInstanceOf(
SampleService::class,
$myObject->s()
);
}
// make sure we can just get any arbitrary object - it should be created for us
public function testInstantiateAnObjectViaGet()
{
$injector = new Injector();
$injector->setAutoScanProperties(true);
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
]
];
$injector->load($config);
$this->assertTrue($injector->has('SampleService'));
$this->assertEquals('SampleService', $injector->getServiceName('SampleService'));
$myObject = $injector->get(OtherTestObject::class);
$this->assertInstanceOf(
SampleService::class,
$myObject->s()
);
// and again because it goes down a different code path when setting things
// based on the inject map
$myObject = $injector->get(OtherTestObject::class);
$this->assertInstanceOf(SampleService::class, $myObject->s());
}
public function testCircularReference()
{
$services = [
'CircularOne' => CircularOne::class,
'CircularTwo' => CircularTwo::class
];
$injector = new Injector($services);
$injector->setAutoScanProperties(true);
$obj = $injector->get(NeedsBothCirculars::class);
$this->assertTrue($obj->circularOne instanceof InjectorTest\CircularOne);
$this->assertTrue($obj->circularTwo instanceof InjectorTest\CircularTwo);
}
public function testPrototypeObjects()
{
$services = [
'CircularOne' => CircularOne::class,
'CircularTwo' => CircularTwo::class,
'NeedsBothCirculars' => [
'class' => NeedsBothCirculars::class,
'type' => 'prototype'
]
];
$injector = new Injector($services);
$injector->setAutoScanProperties(true);
$obj1 = $injector->get('NeedsBothCirculars');
$obj2 = $injector->get('NeedsBothCirculars');
// if this was the same object, then $obj1->var would now be two
$obj1->var = 'one';
$obj2->var = 'two';
$this->assertTrue($obj1->circularOne instanceof InjectorTest\CircularOne);
$this->assertTrue($obj1->circularTwo instanceof InjectorTest\CircularTwo);
$this->assertEquals($obj1->circularOne, $obj2->circularOne);
$this->assertNotEquals($obj1, $obj2);
}
public function testSimpleInstantiation()
{
$services = [
'CircularOne' => CircularOne::class,
'CircularTwo' => CircularTwo::class
];
$injector = new Injector($services);
// similar to the above, but explicitly instantiating this object here
$obj1 = $injector->create(NeedsBothCirculars::class);
$obj2 = $injector->create(NeedsBothCirculars::class);
// if this was the same object, then $obj1->var would now be two
$obj1->var = 'one';
$obj2->var = 'two';
$this->assertEquals($obj1->circularOne, $obj2->circularOne);
$this->assertNotEquals($obj1, $obj2);
}
public function testCreateWithConstructor()
{
$injector = new Injector();
$obj = $injector->create(CircularTwo::class, 'param');
$this->assertEquals($obj->otherVar, 'param');
}
public function testSimpleSingleton()
{
$injector = new Injector();
$one = $injector->create(CircularOne::class);
$two = $injector->create(CircularOne::class);
$this->assertFalse($one === $two);
$one = $injector->get(CircularTwo::class);
$two = $injector->get(CircularTwo::class);
$this->assertTrue($one === $two);
}
public function testOverridePriority()
{
$injector = new Injector();
$injector->setAutoScanProperties(true);
$config = [
'SampleService' => [
'src' => TEST_SERVICES . '/SampleService.php',
'class' => SampleService::class,
'priority' => 10,
]
];
// load
$injector->load($config);
// inject
$myObject = new InjectorTest\TestObject();
$injector->inject($myObject);
$this->assertInstanceOf(SampleService::class, $myObject->sampleService);
$config = [
[
'src' => TEST_SERVICES . '/AnotherService.php',
'class' => AnotherService::class,
'id' => 'SampleService',
'priority' => 1,
]
];
// load
$injector->load($config);
$injector->inject($myObject);
$this->assertInstanceOf(
SampleService::class,
$myObject->sampleService
);
}
/**
* Specific test method to illustrate various ways of setting a requirements backend
*/
public function testRequirementsSettingOptions()
{
$injector = new Injector();
$config = [
OriginalRequirementsBackend::class,
NewRequirementsBackend::class,
DummyRequirements::class => [
'constructor' => [
2018-01-16 19:39:30 +01:00
'%$' . OriginalRequirementsBackend::class
]
]
];
$injector->load($config);
$requirements = $injector->get(DummyRequirements::class);
$this->assertInstanceOf(
OriginalRequirementsBackend::class,
$requirements->backend
);
// just overriding the definition here
$injector->load(
[
DummyRequirements::class => [
'constructor' => [
2018-01-16 19:39:30 +01:00
'%$' . NewRequirementsBackend::class
]
]
]
);
// requirements should have been reinstantiated with the new bean setting
$requirements = $injector->get(DummyRequirements::class);
$this->assertInstanceOf(
NewRequirementsBackend::class,
$requirements->backend
);
}
/**
* disabled for now
*/
public function testStaticInjections()
{
$injector = new Injector();
$config = [
NewRequirementsBackend::class,
];
$injector->load($config);
$si = $injector->get(TestStaticInjections::class);
$this->assertInstanceOf(
NewRequirementsBackend::class,
$si->backend
);
}
public function testSetterInjections()
{
$injector = new Injector();
$config = [
NewRequirementsBackend::class,
];
$injector->load($config);
$si = $injector->get(TestSetterInjections::class);
$this->assertInstanceOf(
NewRequirementsBackend::class,
$si->getBackend()
);
}
public function testCustomObjectCreator()
{
$injector = new Injector();
$injector->setObjectCreator(new InjectorTest\SSObjectCreator($injector));
$config = [
OriginalRequirementsBackend::class,
DummyRequirements::class => [
2018-01-16 19:39:30 +01:00
'class' => DummyRequirements::class . '(\'%$' . OriginalRequirementsBackend::class . '\')'
]
];
$injector->load($config);
$requirements = $injector->get(DummyRequirements::class);
$this->assertEquals(OriginalRequirementsBackend::class, get_class($requirements->backend));
}
public function testInheritedConfig()
{
// Test that child class does not automatically inherit config
$injector = new Injector(['locator' => SilverStripeServiceConfigurationLocator::class]);
Config::modify()->merge(
Injector::class,
MyParentClass::class,
[
'properties' => ['one' => 'the one'],
'class' => MyParentClass::class,
]
);
$obj = $injector->get(MyParentClass::class);
$this->assertInstanceOf(MyParentClass::class, $obj);
$this->assertEquals($obj->one, 'the one');
// Class isn't inherited and parent properties are ignored
$obj = $injector->get(MyChildClass::class);
$this->assertInstanceOf(MyChildClass::class, $obj);
$this->assertNotEquals($obj->one, 'the one');
// Set child class as alias
$injector = new Injector(
[
'locator' => SilverStripeServiceConfigurationLocator::class
]
);
Config::modify()->merge(
Injector::class,
MyChildClass::class,
2018-01-16 19:39:30 +01:00
'%$' . MyParentClass::class
);
// Class isn't inherited and parent properties are ignored
$obj = $injector->get(MyChildClass::class);
$this->assertInstanceOf(MyParentClass::class, $obj);
$this->assertEquals($obj->one, 'the one');
}
public function testSameNamedSingeltonPrototype()
{
$injector = new Injector();
// get a singleton object
$object = $injector->get(NeedsBothCirculars::class);
$object->var = 'One';
$again = $injector->get(NeedsBothCirculars::class);
$this->assertEquals($again->var, 'One');
// create a NEW instance object
$new = $injector->create(NeedsBothCirculars::class);
$this->assertNull($new->var);
// this will trigger a problem below
$new->var = 'Two';
$again = $injector->get(NeedsBothCirculars::class);
$this->assertEquals($again->var, 'One');
}
public function testConvertServicePropertyOnCreate()
{
// make sure convert service property is not called on direct calls to create, only on configured
// declarations to avoid un-needed function calls
$injector = new Injector();
2018-01-16 19:39:30 +01:00
$item = $injector->create(ConstructableObject::class, '%$' . TestObject::class);
$this->assertEquals('%$' . TestObject::class, $item->property);
// do it again but have test object configured as a constructor dependency
$injector = new Injector();
$config = [
ConstructableObject::class => [
'constructor' => [
2018-01-16 19:39:30 +01:00
'%$' . TestObject::class
]
]
];
$injector->load($config);
$item = $injector->get(ConstructableObject::class);
$this->assertTrue($item->property instanceof InjectorTest\TestObject);
// and with a configured object defining TestObject to be something else!
$injector = new Injector(['locator' => InjectorTest\InjectorTestConfigLocator::class]);
$config = [
ConstructableObject::class => [
'constructor' => [
2018-01-16 19:39:30 +01:00
'%$' . TestObject::class
]
],
];
$injector->load($config);
$item = $injector->get(ConstructableObject::class);
$this->assertTrue($item->property instanceof InjectorTest\ConstructableObject);
$this->assertInstanceOf(OtherTestObject::class, $item->property->property);
}
public function testNamedServices()
{
$injector = new Injector();
$service = new TestObject();
$service->setSomething('injected');
// Test registering with non-class name
$injector->registerService($service, 'NamedService');
$this->assertTrue($injector->has('NamedService'));
$this->assertEquals($service, $injector->get('NamedService'));
2017-06-27 00:19:51 +02:00
// Unregister service by name
$injector->unregisterNamedObject('NamedService');
$this->assertFalse($injector->has('NamedService'));
// Test registered with class name
$injector->registerService($service);
$this->assertTrue($injector->has(TestObject::class));
$this->assertEquals($service, $injector->get(TestObject::class));
2017-06-27 00:19:51 +02:00
// Unregister service by class
$injector->unregisterNamedObject(TestObject::class);
$this->assertFalse($injector->has(TestObject::class));
}
public function testCreateConfiggedObjectWithCustomConstructorArgs()
{
// need to make sure that even if the config defines some constructor params,
// that we take our passed in constructor args instead
$injector = new Injector(['locator' => InjectorTest\InjectorTestConfigLocator::class]);
$item = $injector->create('ConfigConstructor', 'othervalue');
$this->assertEquals($item->property, 'othervalue');
}
/**
* Tests creating a service with a custom factory.
*/
public function testCustomFactory()
{
$injector = new Injector(
[
'service' => ['factory' => 'factory', 'constructor' => [1, 2, 3]]
]
);
2017-03-24 03:50:39 +01:00
$factory = $this->getMockBuilder(Factory::class)->getMock();
$factory
->expects($this->once())
->method('create')
->with($this->equalTo('service'), $this->equalTo([1, 2, 3]))
->will(
$this->returnCallback(
function ($args) {
return new InjectorTest\TestObject();
}
)
);
$injector->registerService($factory, 'factory');
$this->assertInstanceOf(TestObject::class, $injector->get('service'));
}
public function testMethods()
{
// do it again but have test object configured as a constructor dependency
$injector = new Injector();
$config = [
'A' => [
'class' => TestObject::class,
],
'B' => [
'class' => TestObject::class,
],
'TestService' => [
'class' => TestObject::class,
'calls' => [
['myMethod', ['%$A']],
['myMethod', ['%$B']],
['noArgMethod']
]
]
];
$injector->load($config);
$item = $injector->get('TestService');
$this->assertTrue($item instanceof InjectorTest\TestObject);
$this->assertEquals(
[$injector->get('A'), $injector->get('B'), 'noArgMethod called'],
$item->methodCalls
);
}
public function testNonExistentMethods()
{
$this->expectException(\InvalidArgumentException::class);
$injector = new Injector();
$config = [
'TestService' => [
'class' => TestObject::class,
'calls' => [
['thisDoesntExist']
]
]
];
$injector->load($config);
$item = $injector->get('TestService');
}
public function testProtectedMethods()
{
$this->expectException(\InvalidArgumentException::class);
$injector = new Injector();
$config = [
'TestService' => [
'class' => TestObject::class,
'calls' => [
['protectedMethod']
]
]
];
$injector->load($config);
$item = $injector->get('TestService');
}
public function testTooManyArrayValues()
{
$this->expectException(\InvalidArgumentException::class);
$injector = new Injector();
$config = [
'TestService' => [
'class' => TestObject::class,
'calls' => [
['method', ['args'], 'what is this?']
]
]
];
$injector->load($config);
$item = $injector->get('TestService');
}
public function testGetThrowsOnNotFound()
{
$this->expectException(InjectorNotFoundException::class);
$injector = new Injector();
$injector->get('UnknownService');
}
public function testGetTrimsWhitespaceFromNames()
{
$injector = new Injector;
$this->assertInstanceOf(MyChildClass::class, $injector->get(' ' . MyChildClass::class . ' '));
}
/**
* Test nesting of injector
*/
public function testNest()
{
// Outer nest to avoid interference with other
Injector::nest();
$this->nestingLevel++;
// Test services
$config = [
NewRequirementsBackend::class,
];
Injector::inst()->load($config);
$si = Injector::inst()->get(TestStaticInjections::class);
$this->assertInstanceOf(TestStaticInjections::class, $si);
$this->assertInstanceOf(NewRequirementsBackend::class, $si->backend);
$this->assertInstanceOf(MyParentClass::class, Injector::inst()->get(MyParentClass::class));
$this->assertInstanceOf(MyChildClass::class, Injector::inst()->get(MyChildClass::class));
// Test that nested injector values can be overridden
Injector::nest();
$this->nestingLevel++;
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
Injector::inst()->unregisterObjects([
TestStaticInjections::class,
MyParentClass::class,
]);
$newsi = Injector::inst()->get(TestStaticInjections::class);
$newsi->backend = new InjectorTest\OriginalRequirementsBackend();
Injector::inst()->registerService($newsi, TestStaticInjections::class);
Injector::inst()->registerService(new InjectorTest\MyChildClass(), MyParentClass::class);
// Check that these overridden values are retrievable
$si = Injector::inst()->get(TestStaticInjections::class);
$this->assertInstanceOf(TestStaticInjections::class, $si);
$this->assertInstanceOf(OriginalRequirementsBackend::class, $si->backend);
$this->assertInstanceOf(MyParentClass::class, Injector::inst()->get(MyParentClass::class));
$this->assertInstanceOf(MyParentClass::class, Injector::inst()->get(MyChildClass::class));
// Test that unnesting restores expected behaviour
Injector::unnest();
$this->nestingLevel--;
$si = Injector::inst()->get(TestStaticInjections::class);
$this->assertInstanceOf(TestStaticInjections::class, $si);
$this->assertInstanceOf(NewRequirementsBackend::class, $si->backend);
$this->assertInstanceOf(MyParentClass::class, Injector::inst()->get(MyParentClass::class));
$this->assertInstanceOf(MyChildClass::class, Injector::inst()->get(MyChildClass::class));
// Test reset of cache
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
Injector::inst()->unregisterObjects([
TestStaticInjections::class,
MyParentClass::class,
]);
$si = Injector::inst()->get(TestStaticInjections::class);
$this->assertInstanceOf(TestStaticInjections::class, $si);
$this->assertInstanceOf(NewRequirementsBackend::class, $si->backend);
$this->assertInstanceOf(MyParentClass::class, Injector::inst()->get(MyParentClass::class));
$this->assertInstanceOf(MyChildClass::class, Injector::inst()->get(MyChildClass::class));
// Return to nestingLevel 0
Injector::unnest();
$this->nestingLevel--;
}
}