When I'm writing my modules, I'm trying to supply them with unit-tests for the most critical parts of the application. However, there are at the moment (Magento 2.1.3) several ways on how to write unit tests:
Different ways of testing
- Integrate it with
bin/magento dev:tests:run unit
and run it on top of the default phpunit settings bundled with Magento. - Write them separately, run them with
vendor/bin/phpunit app/code/Vendor/Module/Test/Unit
and mock everything that is Magento. - Write them separately, mock everything and use a system-global version of PHPUnit.
- Write them separately, run them with
vendor/bin/phpunit
, but still make use of\Magento\Framework\TestFramework\Unit\Helper\ObjectManager
.
Magento 2 and PHPUnit
Besides that, Magento 2 comes bundled with PHPUnit 4.1.0, which is not PHP7-compatible. Type-hinting natives (like string
and `int) and declaring return types in your signatures will throw errors. For example, an interface / class with a method signature like this:
public function foo(string $bar) : bool;
... will not be able to be mocked by PHPUnit 4.1.0. :-(
My current situation
It's due because of this that I'm now mostly writing my unit tests in the third way (by calling a system-global PHPUnit version).
In my setup, I have PHPUnit 5.6 installed globally, so I can solve write proper PHP7-code, but I have to do some tweaks. For example:
phpunit.xml
has to look like this so I can make use of the composer autoloader:
<?xml version="1.0"?>
<phpunit bootstrap="../../../../../../vendor/autoload.php"
colors="true">
<testsuites>
<testsuite name="Testsuite">
<directory>.</directory>
</testsuite>
</testsuites>
</phpunit>
...and in all my setUp()
-methods, I have the following check so I can write my tests with forward-compatibility:
// Only allow PHPUnit 5.x:
if (version_compare(\PHPUnit_Runner_Version::id(), '5', '<')) {
$this->markTestSkipped();
}
This way, when my tests are ran by Magentos' built-in PHPUnit, it doesn't throw an error.
My question
So here's my question: is this a 'healthy' way of writing unit tests? Because it doesn't seem right to me that Magento comes bundled with a whole bunch of tools to aid with testing and I can't use them because I'm using PHP7. I know there are tickets on GitHub that address this issue, but I'm wondering how the community is currently writing it's tests.
Is there a way to write unit tests in Magento 2 so I don't have to 'downgrade' my code and still can use Magentos' built-in helpers for mocking everything the object manager touches? Or is it even bad practice to use the object manager even in your unit tests?
I'm missing a lot of guidance / examples in what's the proper way on how to unit test your own custom modules.