@
@
@smple2016-03-28 16:59:48
PHP
@smple, 2016-03-28 16:59:48

How to test multiple implementations of the same interface in phpunit?

Good afternoon, the following situation arose.
Let's say there are arbitrary interfaces I1 and I2.
There are 3 objects: O1 implements I1, O2 implements I2 and O3 implements I1 and I2 (I know what is bad and that the object should have a single responsibility).
I would like to have a place with a description of tests for I1 and I2 and that these tests can be connected when testing objects O1, O2 and O3.
I was looking at options for interfaces to create an abstract class that inherits from phpunit test case but then the O3 object cannot be tested (multiple inheritance).
The closest option is to create a trait for I1 and I2, which will describe the same behavior for everyone who implements this interface, and inside the test cases, the necessary traits are already connected (depending on what they implement), but then there is no autocomplete in ide.
I have a few more ideas but they all seem like crutches.
Is there any other way to test this?
Can anyone share the best practices.
As an example

<?php

interface MagicIntreface
{
    /**
     * @param $name
     * @return mixed
     * @throws InvalidArgumentException if name not found or not string
     */
    public function get($name);
}

class A implements MagicIntreface
{
    public function get($name)
    {
        if (!is_string($name)) {
            throw new RuntimeException('Invalid name');
        }
        return 'value a';
    }
}

class B implements MagicIntreface
{

    public function get($name)
    {
        if (!is_string($name)) {
            throw new InvalidArgumentException('Name must be a string');
        }
        return 'value b';
    }
}

Accordingly, implementation A does not have a valid exception (it should be InvalidArgumentException and not RuntimeException). Of
course, you can write a test for both implementations.
class ATest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testGetInvalidName()
    {
        $magic = new A;
        $magic->get(123);
    }
}

class BTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testGetInvalidName()
    {
        $magic = new B;
        $magic->get(123);
    }
}

but copy-pasting such checks every time is not very convenient, especially if there are a lot of identical behaviors.
How else can this problem be solved?

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question