Unable to instrument classes in the /vendor directory
kzap opened this issue · 2 comments
I was able to get AspectMock to instrument my own classes in my directory but I can not get it to work on classes in the composer /vendor
directory....
Is this even possible?
I tried adding vendor to my includePaths
but I get the issue in #112
My bootstrap looks basically like this:
require_once __DIR__.'/../vendor/autoload.php'; // composer autoload
$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'appDir' => __DIR__.'/..',
'cacheDir' => __DIR__.'/_data/aopcache',
'includePaths' => [
__DIR__.'/../repo'
],
'excludePaths' => [
__DIR__,
]
]);
Sample of my test code:
$testDataStr = 'var=1&var=2';
$paypalIPN = test::double(new \PayPal\IPN\PPIPNMessage($testDataStr), [
'getRawData' => ['Returned test double'],
]);
$this->assertTrue($paypalIPN->class->hasMethod('getRawData'));
$testData = $paypalIPN->getRawData();
$paypalIPN->verifyInvoked('getRawData'); // fails
fails with:
Expected PayPal\IPN\PPIPNMessage->getRawData to be invoked but it never occurred. Got:
Versions
php 5.6.30
codeception/aspect-mock:2.0.1 @b7f5c50da89419824102400bb4c71988ec33044f
goaop/framework:2.1.2 @6e2a0fe13c1943db02a67588cfd27692bddaffa5
goaop/parser-reflection:1.4.0 @adfc38fee63014880932ebcc4810871b8e33edc9
+1
I want to mock some vendor class, but seems AspectMock is not designed to do this out of the box.
Note: my vendor dir has non-standard location.
For now I solved it like this:
Note: mocked vendor classes may throw an exception when they tries to load another classes from the same package.
// make sure your include paths in this array does not end with a slash '/' symbol
$includeDirsFromVendor = [
ROOT_PATH . '/library/vendor/someVendorName',
ROOT_PATH . '/library/vendor/anotherVendorName/someVendorLib',
];
// add your basic exclude paths to this array
$excludePaths = [
ROOT_PATH . '/tests',
];
foreach (glob(ROOT_PATH . '/library/vendor/*', GLOB_ONLYDIR) as $dir) {
if (!in_array($dir, $includeDirsFromVendor)) {
foreach (glob($dir . '/*', GLOB_ONLYDIR) as $subDir) {
if (!in_array($subDir, $includeDirsFromVendor)) {
$excludePaths[] = $subDir;
}
}
}
}
After this $excludePaths
stores all vendor dirs + subdirs except those which listed in $includeDirsFromVendor
.
$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'cacheDir' => ROOT_PATH . '/tests/_data/cache',
'includePaths' => [
ROOT_PATH,
],
'excludePaths' => $excludePaths,
]);
And it works, at least for a library that I've mocked. But I have feeling that it's better to refactor my code and do not mock vendor classes.
Nice solution. I assume this was done so the code being run does not mock itself
btw tested out the above code and it works well!