Search code examples
testingbddphpspec

Test abstract class through concrete class


I'm really new to PHPSpec and BDD in general so, maybe, my assumption isn't good, in that case please correct me.

Let's consider this scenario

//src/myBundle/Model/FooInterface
interface FooInterface
{
    [...]
}

//src/myBundle/Model/FooAbstractManager
abstract class FooAbastractManager implements FooInterface
{
    public function aCommonMethodForAllConcrete()
    {
        [...]
    }
}

Ok, let's say that aCommonMethodForAllConcrete() share some implemenation with all concrete classes and that I want to write test case only one time.

I've finally (correct me if I'm wrong) had an "idea": create a concrete FooAbstractManager only for test this common method and left all concrete methods tests to concrete classes.

BUT, as I don't want this FooAbstractManager to be part of my src codebase, the perfect situation would be to include that class only in a particular subdirectory of spec folder.

Question: how can I customize that behaviour WITHOUT specify that ALL /src/myBundle/Model name-spaced files will be there (as, maybe tomorrow, I will need to keep a concrete class file right there)?


Solution

  • You are right, you can create a concrete class just for testing. It has to extend the abstract class and provide dummy implementations for the abstract methods of the abstract class (if any).

    Because this class created for testing is just a thin cover of the abstract class, it doesn't provide any functionality on its own and it's used only in a single spec you don't even need to put it into its own file. Just drop it at the end of the spec file.

    This is kind of the "official" way of testing the abstract classes. Check "Limitation #5" on this article written by one of the phpspec creators.