New to Symfony2, I'm building an app that uses an external API to get data. I created a lot of client classes to retrieve and transform each entity from the API, and I defined those classes as services - e.g., I have a FooClient with methods like getAll() or getThoseThatInterestMe($me), which return data from the API.
Now I wanted to create a ApiClientFacade class, which acts as an interface in front of all the XxxClient classes, following the Facade Pattern - e.g., this facade class would have a method getAllFoo(), which in turn would call FooClient::getAll(), and so on...
I could define my facade class as a service as well, but it'd have too many dependencies - I have around 30 client classes. Also, afaik with this approach I'd be loading all 30 dependencies every time, while most of the times I'd only need one dependency...
So, is there a better way to do this?
Use additional ApiClientFactory to move responsibility about "instantiation of ApiClient objects" from your ApiFacade class (which is your initial idea, as I understood).
In some pseudo-php code my idea is:
$api = new ApiFacade(new ApiClientFactory);
$api->sendNotificationAboutUserLogin('username', time());
An example of method:
class ApiFacade {
private $apiFactory;
public function __construct(ApiClientFactory $factory)
{
$this->apiFactory = $factory;
}
public function sendNotificationAboutUserLogin($username, $timeOfOperation)
{
return $this->apiFactory
->createApi('User')
->post(
'notifications',
array('operation' => 'login', 'username' => $username, 'timeOfOperation' => $timeOfOperation)
);
}
}
In this case your Facade class stays injectable (testable), but also becomes simpler instantiatable (you don't need to pass all dependencies into it anymore).
The ApiClientFactory should look like that:
class ApiClientFactory {
private $apiBaseUrl;
public function __construct($apiBaseUrl)
{
$this->apiBaseUrl = $apiBaseUrl;
}
public function createApi($apiName)
{
switch ($apiName) {
case 'User': return new \My\UserApi($this->apiBaseUrl);
default: // throw an exception?
}
}
}
Related
Given I have a factory class responsible for constructing instances of a certain service that has constructor parameters that can only be resolved at runtime, is there a way to leverage container-driven decoration?
Consider the following class which relies on a parameter that is only defined at runtime:
interface IFooService
{
void DoServicyStuff();
}
class MyFooService : IFooService
{
public MyFooService(string somePeskyRuntimeArgument)
{
this.peskyValue = somePeskyRuntimeArgument;
}
public void DoServicyStuff()
{
// do some stuff here with the peskyValue...
}
}
Since the value can only be provided at runtime, we need to move away from the constructor injection and into a method-level parameter passing. This is commonly achieved using a factory implementation like this:
interface IFooServiceFactory
{
IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter);
}
class FooServiceFactory : IFooServiceFactory
{
public IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter)
{
return new MyFooService(heyItsNowAMethodLevelPeskyParameter);
}
}
While this works fine if the intent is to just abstract away the construction of the service, it poses a challenge to decorate the IFooService instance.
For scenarios where no runtime parameter is involved, this can be easily achieved by tapping into the container to provide our service for us. The example below uses the Scrutor library to decorate the interface with a logging decorator implementation:
class FooServiceFactory : IFooServiceFactory
{
private readonly IServiceProvider serviceProvider;
public FooServiceFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider
}
public IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter)
{
return this.serviceProvider.GetRequiredInstance<IFooService>();
}
}
...
services
.AddTransient<IFooService, MyFooService>()
.AddTransient<IFooServiceFactory, FooServiceFactory>()
.Decorate<IFooService, LoggingFooService>();
But since MyFooService takes a primitive value as an argument, we cannot rely on GetRequiredService<T> to obtain the instance, as it will fail to find "a registration for string" when building the concrete class.
Similarly, changing the factory to rely on ActivatorUtilities's .CreateInstance or .CreateFactory methods will end up creating the objects while completely ignoring the container registrations, thus leaving us without any decorator.
I know I have at least 2 options to decorate the objects manually, namely:
Using the factory itself to manually create the decorator:
public IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter)
{
return new LoggingService(
new MyFooService(heyItsNowAMethodLevelPeskyParameter));
}
Using a factory decorator to inject a decorator after the instance is created:
abstract class FooServiceFactoryDecorator : IFooServiceFactory
{
private readonly IFooServiceFactory fooServiceFactory;
protected FooServiceFactory(IFooServiceFactory fooServiceFactory)
{
this.fooServiceFactory = fooServiceFactory;
}
public virtual IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter)
{
return this.fooServiceFactory.CreateService(heyItsNowAMethodLevelPeskyParameter);
}
}
class LoggingFooServiceFactory : FooServiceFactoryDecorator
{
private readonly IFooServiceFactory fooServiceFactory;
public FooServiceFactory(IFooServiceFactory fooServiceFactory)
{
this.fooServiceFactory = fooServiceFactory;
}
public override IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter)
{
return new LoggingFooService(
this.fooServiceFactory.CreateService(heyItsNowAMethodLevelPeskyParameter));
}
}
...
services
.AddTransient<IFooServiceFactory, FooServiceFactory>()
.Decorate<IFooServiceFactory, LoggingFooServiceFactory>()
Neither of these allows me to directly use .Decorate on top of the service interface. The first option works but is heavily coupled (meaning I'd have to keep changing it if I want to add other decorators into the mix), while the second version is less coupled, but still forces me to writing one factory decorator per service decorator and thus leads into a much more complex solution.
Another pain point is dependencies on the decorators themselves (for example, ILogger<T> on the LoggingFooService), which I could potentially solve by leveraging ActivatorUtilities to create the decorators instead of newing them up manually.
I could also potentially generalize the "factory decorator" so that the decoration function is parameterized and thus the class can be reused, but it is still very convoluted and hard to maintain, while also not providing as good a syntax for consumers to add new decorators.
class DecoratedFooServiceFactory<TDecorator> : FooServiceFactoryDecorator
where TDecorator : IFooService
{
private readonly IFooServiceFactory fooServiceFactory;
private readonly IServiceProvider serviceProvider;
public FooServiceFactory(
IFooServiceFactory fooServiceFactory,
IServiceProvider serviceProvider)
{
this.fooServiceFactory = fooServiceFactory;
this.serviceProvider = serviceProvider;
}
public override IFooService CreateService(string heyItsNowAMethodLevelPeskyParameter)
{
return ActivatorUtilities.CreateInstance<TDecorator>(
this.serviceProvider,
this.fooServiceFactory.CreateService(heyItsNowAMethodLevelPeskyParameter));
}
}
...
services
.AddTransient<IFooServiceFactory, FooServiceFactory>()
.Decorate<IFooServiceFactory, DecoratedFooServiceFactory<LoggingFooService>>()
And finally, if I ever want to move away from using a factory and want to change to using the service directly, this will cause a significant setup change where I'd then have to configure all the decorators again in the container directly instead of just removing the factory registration as one normally would do.
How can I use a factory like this, while still keeping the capability of configuring decorators at the container level using the simple Scrutor syntax?
Ok, a couple of disclaimers first:
I agree with Steven here in that this looks like an anti-pattern and you will probably be better off redesigning your code to not require run-time values on service construction.
I additionally want to caution against using scrutor-like Decorate. While much less confident in this than in the first point, I believe hiding logging in decorators is much less convenient in the long run than it seems at first. Or at least that's what I saw after about a year of trying them out.
That said, let's see what can be done.
First, let's put some constraints on where the value is coming from. Specifically, let's say we can have a service providing that value, that looks like this:
public interface IValueProvider
{
string Get();
}
This actually allows us to have quite a bit of range. Implementation of that interface can:
Get value from external API - once or periodically in the background. It can even call it every time Get is called, but this is a very bad idea, as it will make construction asynchronous.
Get value that is stored in memory and allow some other service to update it. Say, expose a 'configuration' endpoint where a user can set a new value every once in a while.
Calculate the value based on some algorithm of your choice.
Once you have this service, you can register it like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IValueProvider, AwesomeValueProvider>();
services.AddSingleton<IFooServiceFactory, FooServiceFactory>();
services.AddTransient<IFooService>(sp =>
{
var factory = sp.GetRequiredService<IFooServiceFactory>();
var valueProvider = sp.GetRequiredService<IValueProvider>();
return factory.Create(valueProvider.Get());
});
}
Hope this helps
I am currently migrating an existent application to Symfony2 that has about 100 controllers with approximately 8 actions in each controller. All the current Actions are named as follow:
public function index(){}
However the default naming convention for Symfony is indexAction().
Is it possible to keep all my current actions and tell Symfony to use as it is without the "Action" word after the method name?
thank you.
Yes, this is possible. You should be able to define routes as normal, but you need to change the way the kernel finds the controller. The best way to do this is to replace/decorate/extends the service 'controller_name_converter'. This is a private service and is injected into the 'controller_resolver' service.
The source code of the class you want to replace is at 'Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser'.
Basically, the code runs like this. The 'bundle:controller:action' you specified when creating the route is saved in the cache. When a route is matched, that string is given back to the kernel, which in turn calls 'controller_resolver' which calls 'controller_name_resolver'. This class convert the string into a "namespace::method" notation.
Take a look at decorating services to get an idea of how to do it.
Here is an untested class you can work with
class ActionlessNameParser
{
protected $parser;
public function __construct(ControllerNameParser $parser)
{
$this->parser = $parser;
}
public function parse($controller)
{
if (3 === count($parts = explode(':', $controller))) {
list($bundle, $controller, $action) = $parts;
$controller = str_replace('/', '\\', $controller);
try {
// this throws an exception if there is no such bundle
$allBundles = $this->kernel->getBundle($bundle, false);
} catch (\InvalidArgumentException $e) {
return $this->parser->parse($controller);
}
foreach ($allBundles as $b) {
$try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';
if (class_exists($try)) {
// You can also try testing if the action method exists.
return $try.'::'.$action;
}
}
}
return $this->parser->parse($controller);
}
public function build($controller)
{
return $this->parser->build($controller);
}
}
And replace the original service like:
actionless_name_parser:
public: false
class: My\Namespace\ActionlessNameParser
decorates: controller_name_converter
arguments: ["#actionless_name_parser.inner"]
Apparently the Action suffix is here to distinguish between internal methods and methods that are mapped to routes. (According to this question).
The best way to know for sure is to try.
// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class HelloController
{
/**
* #Route("/hello/{name}", name="hello")
*/
public function indexAction($name)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
}
}
Try to remove the Action from the method name and see what happens.
I have model class that calls mailer class inside one of its methods:
class someModel{
public function sendEmail($data){
$mailer = new Mailer();
$mailer->setFrom($data['from']);
$mailer->setTo($data['to']);
$mailer->setSubject($data['subject']);
return $mailer->send();
}
}
How can I test sendEmail method? Maybe I should mock mailer class and check if all these mailer methods were called in sendMail method?
Your help would be appreciated.
IMO wrapping the Mailer class does not solve the problem you're facing, which is you don't have control over the Mail instance being used.
The problem comes from creating the dependencies inside the object that needs them instead of injecting them externally like this:
class someModel{
private $mailer;
public function __construct(Mailer $mailer) {
$this->mailer = $mailer;
}
public function sendEmail($data){
$this->mailer->setFrom($data['from']);
$this->mailer->setTo($data['to']);
$this->mailer->setSubject($data['subject']);
return $this->mailer->send();
}
}
When creating the someModel instance, you must pass a Mail instance (which is an external dependency). And in the test you can pass a Mail mock that will check that the correct calls are being made.
Alternative:
If you feel that injecting a Mail instance is bad (maybe because there are lots of someModel instances), or you just can't change your code this way, then you could use a Services repository, that will keep a single Mail instance and that allows you to set it externally (again, in the test you would set a mock).
Try a simple one like Pimple.
I would (and have in my own code with Mailer!) wrap your instance of Mailer inside a class that you write. In other words, make your own Email class that uses Mailer under the hood. That allows you to simplify the interface of Mailer down to just what you need and more easily mock it. It also gives you the ability to replace Mailer seamlessly at a later date.
The most important thing to keep in mind when you wrap classes to hide external dependencies is keep the wrapper class simple. It's only purpose is to let you swap out the Email libraries class, not provide any complicated logic.
Example:
class Emailer {
private $mailer = new Mailer();
public function send($to, $from, $subject, $data) {
$this->mailer->setFrom($from);
$this->mailer->setTo($to);
...
return $mailer->send();
}
}
class EmailerMock extends Emailer {
public function send($to, $from, $subject, $data) {
... Store whatever test data you want to verify ...
}
//Accessors for testing the right data was sent in your unit test
public function getTo() { ... }
...
}
I follow the same pattern for all classes/libraries that want to touch things external to my software. Other good candidates are database connections, web services connections, cache connections, etc.
EDIT:
gontrollez raised a good point in his answer about dependency injection. I failed to explicitly mention it, but after creating the wrapper the way you would want to use some form of dependency injection to get it into the code where you want to use it. Passing in the instance makes it possible to setup the test case with a Mocked instance.
One method of doing this is passing in the instance to the constructor as gontrollez recommends. There are a lot of cases where that is the best way to do it. However, for "external services" that I am mocking I found that method became tedious because so many classes ended up needing the instance passed in. Consider for example a database driver that you want to Mock for your tests, but you use in many many different classes. So instead what I do is create a singleton class with a method that lets me mock the whole thing at once. Any client code can then just use the singleton to get access to a service without knowing that it was mocked. It looked something like this:
class Externals {
static private $instance = null;
private $db = null;
private $email = null;
...
private function __construct() {
$this->db = new RealDB();
$this->mail = new RealMail();
}
static function initTest() {
self::get(); //Ensure instance created
$db = new MockDB();
$email = new MockEmail();
}
static function get() {
if(!self::$instance)
self::$instance = new Externals();
return self::$instance;
}
function getDB() { return $this->db; }
function getMail() { return $this->mail; }
....
}
Then you can use phpunit's bootstrap file feature to call Externals::initTest() and all your tests will be setup with the mocked externals!
First, as RyanW says, you should write your own wrapper for Mailer.
Second, to test it, use a mock:
<?php
class someModelTest extends \PHPUnit_Framework_TestCase
{
public function testSendEmail()
{
// Mock the class so we can verify that the methods are called
$model = $this->getMock('someModel', array('setFrom', 'setTo', 'setSubject', 'send'));
$controller->expects($this->once())
->method('setFrom');
$controller->expects($this->once())
->method('setTo');
$controller->expects($this->once())
->method('setSubject');
$controller->expects($this->once())
->method('send');
$model->sendEmail();
}
}
The above code is untested, but it basically mocks the someModel class, creating dummy functions for each each function called within sendEmail. It then tests to make sure each of the functions called by sendEmail is called exactly once when sendEmail is called.
See the PHPUnit docs for more info on mocking.
I have started using Symfony's console components to build various cli tools.
I am currently slapping together such a console app, that has require various configurations, some of which are shared among commands, other configs are unique to the command.
At first I was using a helper class, with a static function call to load a regular configuration array.
Yesterday I refactored this and now load configuration in the config component, along with the treeBuilder mechanism for validation. This is all done in the main console script, not in the "command" classes.
$app = new Application('Console deployment Application', '0.0.1');
/**
* Load configuration
*/
$configDirectories = array(__DIR__.'/config');
$locator = new FileLocator($configDirectories);
$loader = new YamlConfigLoader($locator);
$configValues = $loader->load(file_get_contents($locator->locate("config.yml")));
// process configuration
$processor = new Processor();
$configuration = new Configuration();
try {
$processedConfiguration = $processor->processConfiguration(
$configuration,
$configValues
);
// configuration validated
var_dump($processedConfiguration);
} catch (Exception $e) {
// validation error
echo $e->getMessage() . PHP_EOL;
}
/**
* Load commands
*/
foreach(glob(__DIR__ . '/src/Command/*Command.php') as $FileName) {
$className = "Command\\" . rtrim(basename($FileName), ".php");
$app->addCommands(array(
new $className,
));
}
$app->run();
Currently, the only means to setup the configuration is to setup the code that loads the configuration in a separate class and call this class in in the configure() method of every method.
Maybe there is a more "symfonyish" way of doing this that I missed, I also would like to avoid having the entire framework in codebase, this is meant to be a lightweight console app.
Is there a way to pass the processed configuration to the commands being invoked, using DI or some other method I am not aware of?
Manual Injection
If you wany to keep things light and only have one (the same) configuration object for all commands, you don't even needa DI container. Simply create the commands like this:
...
$app->addCommands(array(
new $className($configuration),
));
Although you have to be aware of the trade-offs, e.g. you will have to have more effort extending this in the future or adjust to changing requirements.
Simple DI Container
You can of course use a DI container, there is a really lightweight container called Twittee, which has less than 140 characters (and thus fits in a tweet). You could simply copy and paste that and add no dependency. In your case this may end up looking similar to:
$c = new Container();
$c->configA = function ($c) {
return new ConfigA();
};
$c->commandA = function($c) {
return new CommandA($c->configA());
}
// ...
You then would need to set that up for all your commands and configurations and then simply for each command:
$app->addCommand($c->commandA());
Interface Injection
You could roll your own simple injection mechanism using interfaces and setter injection. For each dependency you want to inject you will need to define an interface:
interface ConfigAAwareInterface {
public function setConfigA(ConfigA $config);
}
interface ConfigBAwareInterface {
public function setConfigA(ConfigA $config);
}
Any class that needs the dependency can simply implement the interface. As you will mostly repeat the setters, make use of a trait:
trait ConfigAAwareTrait {
private $config;
public function setConfigA(ConfigA $config) { $this->config = $config; }
public function getConfigA() { return $this->config }
}
class MyCommand extends Command implements ConfigAAwareInterface {
use ConfigAAwareTrait;
public function execute($in, $out) {
// access config
$this->getConfigA();
}
}
Now all that is left is to actually instantiate the commands and inject the dependencies. You can use the following simple "injector class":
class Injector {
private $injectors = array();
public function addInjector(callable $injector) {
$this->injectors[] = $injector;
}
public function inject($object) {
// here we'll just call the injector callables
foreach ($this->injectors as $inject) {
$inject($object);
}
return $object;
}
}
$injector = new Injector();
$configA = new ConfigA();
$injector->addInjector(function($object) use ($configA) {
if ($object instanceof ConfigAAwareInterface) {
$object->setConfigA($configA);
}
});
// ... add more injectors
Now to actually construct a command, you can simply call:
$injector->inject(new CommandA());
And the injector will inject dependencies based on the implemented interfaces.
This may at first seem a little complicated, but it is in fact quite helpful at times.
However, if you have multiple objects of the same class that you need to inject (e.g. new Config("path/to/a.cfg") and new Config("path/to/b.cfg")) this might not be an ideal solution, as you can only distinguish by interfaces.
Dependency Injection Library
You can of course also use a whole library and add that as dependency. I have written a list of PHP dependency injection containers in a separate answer.
I want to write unit test for a class that contains linq to sql codes . I mean inside each method I have created a new DbContext and done database jobs .
I searched the web . first I came to use repository and Unit of Work patterns but I figured out that DbContext itself is a unit of work and its dbset works as repositories . another point is that I think there is no need to test Linq part because it works as it should ( tested by .net team ) . I want to test the logic I have added to the code . so I decided to create an interface with necessary methods with two implementations , one uses linqToSql while another is just a mock . something like this :
public interface IDbManager
{
bool Insert(MyEntity newEntity);
}
public class RealDbManager:IDbManager
{
public bool Insert(MyEntity newEntity)
{
using (DbDataContext db = new DbDataContext())
{
db.MyEntities.InsertOnSubmit(newEntity);
db.SubmitChanges();
}
}
}
public class MockDbManager:IDbManager
{
public bool Insert(MyEntity newEntity)
{
return true;
}
}
is the whole idea correct ? if so is this a correct implementation ?
is it possible to define DbDataContext as a class variable instead of creating new instance inside each method ?
You have the right general idea for a start. Your Mock Insert method should save the entity to some in-memory store so that subsequent queries will return the inserted information, as would be expected. But the very basic idea of having an interface, with a 'real' and a 'mock' implementation is there.
Remember that when using your Mock in tests, you are testing your other code that uses the mock - not the mock itself.
As for defining the DataContext as a member variable; you could use an IDisposable pattern for it, like so:
public class RealDbManager:IDbManager, IDisposable
{
DbDataContext db = new DbDataContext();
public bool Insert(MyEntity newEntity)
{
{
db.MyEntities.InsertOnSubmit(newEntity);
db.SubmitChanges();
}
}
public void Dispose()
{
db.Dispose();
}
}
You would just have to be sure to dispose of your DbManager, then.
Yes. The only thing I would avoid is to create an actual mocked class (in this case it should be called Fake), but using a mocking engine.
In your question you mention two kind of tests. First is testing the behavior of your class, the second is testing the integration of it. They seem the same but it's not.
In the first you need to mock your class to test its 'connection' against your other classes this way (using Moq):
[Test]
public void Test()
{
var entity = new Entity();
var mocked = new Mock<IDbManager>();
//you are telling the moq engine everytimes it finds an invocation of your repository
//to return true as you did in you mocked class
mocked.Setup( x => x.Insert( entity ) ).Returns( true );
var classUnderTest = new ClassUnderTest( mocked.Object );
//in this method you invoke your repository
var ret = classUnderTest.DoSomething( entity );
//assertions
Assert.Equal( something, ret);
//eventually you can verify that your repository has been hit once
mocked.Verify( x => x.Insert( It.IsAny<Entity>), Times.Once);
}
in the later as you correctly state, you have nothing to test on linq (Microsoft did it for us), but in case you need to verify the correctness of your linq you can do it only against a real db (or using a repository pattern against a fake repository). This is an integration test and it's has nothing to share with mocking.
To decouple your class from DbContext you could use repository pattern. Have a look at this article. http://dotnetspeak.com/index.php/2011/03/repository-pattern-with-entity-framework/