This works for us but we haven't yet looked into moving them to a separate location to address 6.)
1.) Place your integration tests under dev/tests/integration/testsuite/Vendor
2.) copy dev/tests/integration/phpunit.dist.xml
to
dev/tests/integration/phpunit.xml
and replace
<directory suffix="Test.php">testsuite</directory>
<directory suffix="Test.php">../../../update/dev/tests/integration/testsuite</directory>
<exclude>testsuite/Magento/Test/Integrity</exclude>
<exclude>testsuite/Magento/MemoryUsageTest.php</exclude>
with
<directory suffix="Test.php">testsuite/Vendor</directory>
3.) run it ../../../vendor/bin/phpunit
or with ../../../vendor/bin/phpunit path/to/tests
from the dev/test/integration folder
Please note that the integration tests take longer than 15 seconds, at least on first run as it essentially installs Magento. You can save on subsequent runs if you use
<const name="TESTS_CLEANUP" value="disabled"/>
in your phpunit.xml
Given the information you posted, I suspect that the class \Custom\Shipping\Helper\Config
implements (or inherits) public function __call()
from a parent class and that the method getProductTypes()
is not a real method but rather a "magic getter".
Magic methods have to be explicitly specified on generated test doubles, otherwise they can not be stubbed for specific return values or otherwise configured.
Try to create the stub as follows:
$this->configHelperMock = $this->getMockBuilder(\Custom\Shipping\Helper\Config::class)
->setMethods(['getProductTypes'])
->disableOriginalConstructor()
->getMock();
This will only stub that one method on the generated test double class.
If you want the test double to stub all methods, not just the one magic getter, while still specifying additional "magic" methods, you have to specify all methods, for example like so:
$methodsToStub = array_merge(
get_class_methods(\Custom\Shipping\Helper\Config::class),
['getProductTypes']
);
$this->configHelperMock = $this->getMockBuilder(\Custom\Shipping\Helper\Config::class)
->setMethods($methodsToStub)
->disableOriginalConstructor()
->getMock();
That is one of the reasons to favor real methods over magic methods.
I'm not 100% sure this is the reason why you are experiencing this issue since you didn't post the source of \Custom\Shipping\Helper\Config
, but please let me know if this helps.
I can't stop myself from adding the following suggestions, too:
Use the PHP 5.5 ::class
constant instead of string class names, that way your IDE (hopefully PHPStorm) can help you find typos.
E.g. $this->getMockBuilder(\Custom\Shipping\Helper\Config::class)
Whats more, you can also use class imports for readability, so in your case just $this->getMockBuilder(Config::class)
In Unit tests, don't use the ObjectManager at all. Just instantiate your class with new
, since all dependencies are test doubles anyway.
Less magic makes for easier debugging. Especially like in your case where there is only a single dependency.
$this->sourceModel = new \Custom\Shipping\Model\Config\Source\ProductTypes(
$this->configHelperMock
);
Use more descriptive names for the test methods. It pays off a few months later when the under test has already been forgotten and suddenly the test breaks after an upgrade or similar change.
E.g. testToArrayReturnsIdenticalKeysAndValues()
Best Answer
The best I can suggest for now is reading up on PHP Unit and looking at other test scripts provided with the code base. I do not recall more unit testing examples being high on the doc teams list at the moment.
Some other reading that might be useful.