How use class interfaces when using PHPSpec - php

When testing with PHPSpec how can I use class interfaces injected into my methods rather then the actual concrete class?
For example I have a Product class that injects a VariationInterface into a method:
/**
* ...
*/
public function addVarient(VarientInterface $varient)
{
return $this->varients->add($varient);
}
Although since PHPSpec has no IOC container to bind VarientInterface to Varient I cant really test my classes.
Is it not best practice to code to an interface and not a concrete class?

You can mock concrete classes and intefaces in PHPSpec.
Please verify this example:
<?php
//file spec/YourNameSpace/ProductSpec.php
namespace spec\YourNameSpace\Product;
use YourNameSpace\VarientInterface;
use PhpSpec\ObjectBehavior;
class ProductSpec extends ObjectBehavior
{
function it_is_varients_container(VarientInterface $varient)
{
$this->addVarient($varient);
$this->getVarients()->shouldBe([$varient]);
}
}
You just pass VarientInterface as parameter to test method.
This VarientInterface is mocked underneath by PhpSpec (really by Prophecy).
Please check offical phpspec documentaion about mocking http://www.phpspec.net/docs/introduction.html#prophet-objects

Related

How do i create a mock object that uses an array of traits?

I am currently on PHPUnit v5.7.27
I would like to create a mock object that uses an array of traits. How would I go about this? I only see getMockForTrait as a way to create a mock object using a single trait. My issue is that the trait requires the existence of another trait at the class level.
Update: More context to the issue
Given:
trait GetSet {
public function __call(){ /* does some magic */
}
trait RepositoryAware {
public function getRepository(string $name)
{
/* makes use of the GetSetTrait*/
}
}
class Controller
{
use GetSet;
use RepositoryAware;
}
Given the limitations of PHP, I can not simply put a use GetSet on the RepositoryAware trait because other traits that the controller imports could also bring the GetSet trait. Furhtermore, the controller class itself could be using the behavior provided by the GetSet trait.
The current solution I have is to create a Dummy Class that imports both traits and mock that class instead:
class RepositoryAwareClass
{
use GetSet;
use RepositoryAware;
}
Like this I am able to properly test the behavior provided by the RepositoryAware trait while at the same time composing its requirement of the GetSet trait.
Mocking concept was built with the idea that you would be using dependency injection. I can certainly see why you may not want to use dependency injection with this multiple inheritance like model that php uses called "Traits". Mocking tools like the one built for phpunit was built to substitute instances of objects not classes/interfaces/traits themselves. PHP Traits are more like having a static dependency instead of a dependency on an instance of an object. However, even if you were using traits and assuming a trait was basically the same as a class, according to mocking best practices should test the trait as its own test instead of testing a trait through another class. If you want to mock the trait itself you may want to try to revisit your design as I do not believe it can be done. You can certainly mock a trait and test that trait but you cannot mock a trait and then inject it as a dependency on an object. Imagine that a class for example implements an interface, mocking a trait would be the same a mocking an interface that a class implements, its not possible. You can only mock an interface of an object that a class depends upon through setter or constructor based dependency injection. Another example would be to try and mock the class that the class under test inherits from. You can't do that either. Perhaps in the javascript world this type of thing could be useful and from some people's point of view desired, but I think if you want to use mocking you would need to stick with object dependency injection instead of static use of traits.
So what's the alternative? I think the following example would be how to use perhaps "traditional" OOP practices with mocking to achieve your goal of sharing functionality without using inheritance. The example also makes your dependencies more explicit. And for the record, I applaud you for NOT using inheritance.
<?php
interface GetterSetter {
public function __call();
}
interface RepositoryProvider {
public function getRepository(string $name);
}
class GetSet implements GetterSetter {
public function __call() {
/* does some magic */
}
}
class DefaultRepository implements RepositoryProvider, GetterSetter {
/**
* #var GetterSetter
*/
private $_getterSetter;
public function __construct(GetterSetter $getterSetter) {
$this->_getterSetter = $getterSetter;
}
public function getRepository(string $name) {
// makes use of the GetSetTrait
$this->__call();
}
public function __call() {
// makes use of the GetSetTrait
$this->_getterSetter->__call();
}
}
class Controller implements RepositoryProvider, GetterSetter {
/**
* #var RepositoryProvider
*/
private $repositoryProvider;
public function __construct() {
$this->repositoryProvider = new DefaultRepository(new GetSet());
}
public function getRepository(string $name) {
return $this->repositoryProvider->getRepository($name);
}
public function __call() {
$this->repositoryProvider->__call();
}
}
In general I feel like the PHP community took a wild left turn, trying to be more like javascript and I feel that traits can walk you into a corner. This is a very good example of such a corner. I would really avoid them, at least for now. In the long run I believe Generics would be the better solution to your problem of needing a generic GetSet piece of code but generics haven't been implemented in php yet :-(.

How to access get method in a Test Class Symfony2

I have to write a test class to test my service methods. In my controllers I could access the service by doing $service = $this->get('myService'); and I could access my methods by doing $service->someMethod();.
Now I want to write a test class to test some of the service methods, I tried doing like the doc :
class ServiceTest extends \PHPUnit_Framework_TestCase {
public function testSomeMethod() {
$service = $this->get('myService');
....
}
}
When I launch the test I get something like : Fatal error : Call to undefined method XXX\XXXBundle\Tests\Services\ServicesTest::get() in ...
So my question is how can I use get method to be able to call my service methods
You don't need to use the container in order to test services and other classes.
You should create a new instance of the class and inject the dependencies using test doubles.
Test doubles
- since you don't want to write a functional testing and to use the real dependencies you should be using a test double.
for example if one of the service dependencies is the EntityManager what would happen is that a new entries would be inserted into the Database (or deleted from it) and its not the purpose of Unit testing (you do need to check this tho if you are writing a functional test).
And that's how you should approach this kind of testings:
public function testSomeServiceAdd()
{
$dependencyOne = $this->getMockBuilder('Acme\SomeBundle\DependencyOne')->
disableOriginalConstructor()->
getMock();
$dependencyTwo = $this->getMockBuilder('Acme\SomeBundle\DependencyTwo')->
disableOriginalConstructor()->
getMock();
$service = new SomeService($dependencyOne, $dependencyTwo);
$response = $service->add(1, 2);
$this->assertEquals($response, 3);
}
As you can see I am "mocking" the dependencies and injecting it into the service, after that i'm calling the method and asserting the result.
I would also like to suggest a Mocking framework instead of using the built-in PHPUnit mocking functions. it's easier to use and it has much more mocking functionality:
https://github.com/danrevah/ShortifyPunit
To test your services you should extend the KernelTestCase class.
class ServiceTest extends KernelTestCase
{
private $service;
/**
* {#inheritDoc}
*/
public function setUp()
{
self::bootKernel();
$this->service = static::$kernel->getContainer()
->get('my_service')
;
}
}

How to properly inject dependency into Laravel artisan command?

Basically I want to call a method on a repository Repository.php from a laravel command.
Example\Storage\Repository.php
Example\Storage\RepositoryInerface.php
Example\Storage\RepositoryServiceProvider.php
I expect Interface in the command constructor and then set it to the protected variable.
In the service provider I bind the Interface to Repository class.
Right now, in start/artisan.php I just write:
Artisan::add(new ExampleCommand(new Repository());
Can I use an interface here? What is the correct way? I am confused.
Thanks in advance.
EDIT: To clarify, it only works the way it is now, but I don't want to hardcode a concrete class while registering the artisan command.
You could use the automatic dependency injection capabiltiies of the IoC container:
Artisan::add(App::make('\Example\Commands\ExampleCommand'));
// or
Artisan::resolve('\Example\Commands\ExampleCommand');
If ExampleCommand's constructor accepts a concrete class as its parameter, then it'll be injected automatically. If it relies on the interface, you need to tell the IoC container to use a specific concrete class whenever the given interface is requested.
Concrete (ignoring namespaces for brevity):
class ExampleCommand ... {
public function __construct(Repository $repo) {
}
}
Artisan::resolve('ExampleCommand');
Interface (ignoring namespaces for brevity):
class ExampleCommand ... {
public function __construct(RepositoryInterface $repo) {
}
}
App::instance('RepositoryInterface', new Repository);
Artisan::resolve('ExampleCommand');
You may use the interface in the constructor to type hint the depended object but you have to bind the concrete class to the interface in the IoC container using something like following, so it'll work.
App::bind('Example\Storage\RepositoryInerface', 'Example\Storage\Repository');
Read more on the documentation.

How does laravels IoC/Dependency Injector intsantiate to static instances?

So this is probably a rather simple question but I can't seems to find a very direct answer. I supposed to could keep reading the source until i figure it out but I was hoping to get a bit of understand of the process of doing so.
I understand IoC and Dependency injection, I am certainly not very experienced in either but I have a good understand of what they are trying to accomplish. So how does this Laravel instantiate to static instances? I know it uses PHP reflections but I'm still lost on the part of going from non-static to static methods. Also I know Laravel is not the only framework to implement such a design but its my preferred and most understood framework.
When you call a static method on a facade it is being handled by the magic __callStatic method on the Facade class. This method gets the underlying class that serves the facade and proxies the static call to it.
Let's look at an example facade:
<?php
class MyFacade extends Facade {
public function getFacadeAccessor() { return "MyFacade"; }
}
With this example when we make a call to the class in a static manner such as: MyFacade::doSomething() no static method exists on the class. The underlying Facade base class however contains a __callStatic method that will be called.
Facade Class Source Code
public static function __callStatic($method, $args)
{
$instance = static::resolveFacadeInstance(static::getFacadeAccessor());
switch (count($args))
{
case 0:
return $instance->$method();
// Snipped for brevity...
This method then looks up the underlying class to service the facade. If the getFacadeAccessor method on the facade returns a string then a matching entry in the application's IOC container is used (i.e. $app['MyFacade']). If we returned an object from the getFacadeAccessor method it would be used instead (i.e. public function getFacadeAccessor(){ return new MyClass(); }
Turns out that Laravel instantiate the classes under the hood! In this site, the guy makes you understanding a little more of the Laravel's core by using it to create a new facade. In the way, he explains how tit works!
It quite simple, actualy:
1 - You create a classe which extends from Laravel's Facade class with a single call like:
<?php namespace Name\Space;
use Illuminate\Support\Facades\Facade;
class MyClass extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'myclass'; }
}
... that's make Laravel look for $app['myclass']. So, the ServiceProvider will bind the myclass to MyClass (according to Laravel's conventions).
2 - For that, of course, you'll have to create a Service Provider.
The Service Provider will be responsible for returning the namespace, in this case Name\Space, for the class(es) that you may want to 'turn into facades'.
3 - You'll have to register your Service Provider in the providers array in the app/config/app.php.
Now, if you look with more attention, you'll realise that what Laravel does is just import a namespace and understanding it as it was a class, as well. Under the hood, it will call a instance, but for user (programmer) it will looks like a static call.
I hope I had been clear about it! Look the link I gave to you up there and HAVE FUN! :D

Mock interface and trait simultaneously

Is it possible to build object like this (implementing interface and using a trait at the same time) in PHPUnit mock builder?
<?php
class FooClassThatD implements BarInterface
{
use BazTrait;
}
I don't think this is possible with the native mock object methods because they use a specific template to mock a class with a trait that doesn't allow any extension points. You can get around it easily with a test-specific class from which you build your mock.
abstract class BarWithBazTraitTestClass implements BarInterface
{
use BazTrait;
}
Create a mock for this class as you would any other abstract class.
$mock = $this->getMockForAbstractClass('BarWithBazTraitTestClass');

Categories