Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to instrument classes in the /vendor directory #139

Open
kzap opened this issue Sep 16, 2017 · 2 comments
Open

Unable to instrument classes in the /vendor directory #139

kzap opened this issue Sep 16, 2017 · 2 comments

Comments

@kzap
Copy link

kzap commented Sep 16, 2017

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

@kzap kzap changed the title Instrumenting classes in the /vendor directory Unable to instrument classes in the /vendor directory Sep 16, 2017
@AndrewSologor
Copy link

AndrewSologor commented Dec 7, 2017

+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.

@kzap
Copy link
Author

kzap commented Dec 7, 2017

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants