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

Need some help. #33

Closed
m1ome opened this issue Feb 23, 2015 · 37 comments
Closed

Need some help. #33

m1ome opened this issue Feb 23, 2015 · 37 comments
Labels

Comments

@m1ome
Copy link
Collaborator

m1ome commented Feb 23, 2015

I am trying to override a Phalcon model based method "find, findFirst" and e.t.c.
They are inside c-extension. Could them be override over Monkey patching ?

Or there is some way to do this overload default model namespace through Interceptor?

@jails
Copy link
Contributor

jails commented Feb 23, 2015

Monkey patching only works if you are calling explicitly a "built-in function" or instantiating a "built-in class". But it doesn't work for "built-in inheritance" unfortunately. The only solution would be to introduce a new patcher imo (like described here).

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 23, 2015

It looks like in solution line links is broken.

@jails
Copy link
Contributor

jails commented Feb 23, 2015

It's just a comment of the issue n°5

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 23, 2015

You mean write a patcher something like Quit patcher and inject it into patcher namespace. https://github.com/crysalead/kahlan/blob/master/src/cli/Kahlan.php#L352-L365 like here?

@jails
Copy link
Contributor

jails commented Feb 23, 2015

Yup, I mean a patcher which rewrite all:

class MyModel extends \Phalcon\Mvc\Model

to something like:

class MyModel extends \a\custom\layer\Class

The a\custom\layer\Class class could be a class in your spec directory which extends Phalcon\Mvc\Model with all its method overridden, or a more complex patcher should be able to create such class automatically. For example by using $layerClass = Stub::classname(['extends' => 'Phalcon\Mvc\Model']). Unfortunately Stub::classname() won't work out of the box since right now the only "layered methods" are the abstract one but I think I can sketch up something quickly.

@jails
Copy link
Contributor

jails commented Feb 23, 2015

Just updated the Stub class to allow a layer parameter 6b4ba7a

So the deal is to have a patcher which is able to replace all extends \Phalcon\Mvc\Model to extends \$layerClass where $layerClass is $layerClass = Stub::classname(['extends' => 'Phalcon\Mvc\Model', 'layer' => true]). Btw the patcher will probably need to be configured with a list of fully namespaced class name to "layerize".

@jails
Copy link
Contributor

jails commented Feb 23, 2015

And I sketched up the principle of a layer patcher in this commit f74002c in the dev branch.

@jails
Copy link
Contributor

jails commented Feb 25, 2015

So on the dev branch adding the following:

     ...
     $patchers->add('layer', new Layer([
         'override' => [
             'Phalcon\Mvc\Model'
         ]
     ]));

inside a patchers endpoint should allow you to stub any kind of model's methods extended from Phalcon\Mvc\Model.

Feel free to keep me updated if this patcher still have room for improvement according to your specific usage with Phalcon.

@jails jails closed this as completed Feb 25, 2015
@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

Iside config i set:

Filter::register('app.patchers', function($chain) {
    $interceptor = Interceptor::instance();
    $patchers = $interceptor->patchers();
    $patchers->add('layer', new Layer([
        'override' => [
            'Phalcon\Mvc\Model'
        ]
    ]));

    return $chain->next();
});

Then i have a model:

<?php
namespace Api\Models;

class ApiLog extends \Phalcon\Mvc\Model {

}

And spec:

<?php

use kahlan\plugin\Stub;

describe("Stub with a layer filter", function() {

    it("should stub a layer", function() {

        Stub::on('Api\Models\ApiLog')->method('create', function($data=null, $whiteList=null) {
            return true;
        }); 

        $model = new \Api\Models\ApiLog();
        expect($model->create())->toBe(true);

    });

});

And it fails. (It return false)

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

After i clean-up /tmp/kalhan it seems start working layering. But i got an error:

PHP Fatal error:  Cannot override final method Phalcon\Mvc\Model::__construct() in /vagrant/crm/phalcon_test/temp/vendor/crysalead/kahlan/src/plugin/Stub.php(226) : eval()'d code on line 73

It seems that no need in layer to patch-up a finally methods.

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

Fixed this adding on plugin/Stub:432 line:

if ($method->getModifiers() & ReflectionMethod::IS_FINAL) continue;

And got new error:

PHP Fatal error:  Declaration of kahlan\spec\plugin\stub\Stub0::assign() must be compatible with Phalcon\Mvc\ModelInterface::assign($data, $columnMap = NULL) in /vagrant/crm/phalcon_test/temp/vendor/crysalead/kahlan/src/plugin/Stub.php(226) : eval()'d code on line 72

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

Fixed this. I will prepare a patch

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

@jails it works now perfectly.

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

On a second run i have:

PHP Fatal error:  Class 'kahlan\spec\plugin\stub\Stub0' not found in /tmp/kahlan/vagrant/crm/wtm.dev/app/models/Cards.php on line 14

This line is:

class Cards extends \kahlan\spec\plugin\stub\Stub0 {

@jails
Copy link
Contributor

jails commented Feb 25, 2015

Ah yeah indeed, didn't think about that, I guess we will need to embed the sub inside the cached file.

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

I think it will be more handy to you.

@jails
Copy link
Contributor

jails commented Feb 25, 2015

I thought about something like that 8a52782
It should work but wasn't able to test it since I haven't Phalcon installed.

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

@jails it broken now. Just failing and that's all. I have a file, and it seems to be normal, but it just failing tests.

@jails
Copy link
Contributor

jails commented Feb 25, 2015

@m1ome what the cached file in /tmp/kahlan looks like ?

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

Now

PHP Parse error:  syntax error, unexpected '<' in /tmp/kahlan/vagrant/crm/phalcon_test/temp/app/models/ApiLog.php on line 6

It looks like you generate <?php twice.

@jails
Copy link
Contributor

jails commented Feb 25, 2015

Ah yeah I fucked up the last dev commit.

@jails
Copy link
Contributor

jails commented Feb 25, 2015

Should work better now but you will need to update https://github.com/crysalead/jit to its last master.

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

@jails yes, now it's working as it should.

@m1ome
Copy link
Collaborator Author

m1ome commented Feb 25, 2015

@jails thank 👍 !

@jails
Copy link
Contributor

jails commented Feb 25, 2015

Cool, I'm merging it to master then.

@jails jails added the question label Mar 20, 2015
@shivshankarsomu
Copy link

@jails Can u please help us with the undermentioned.
We are using Phalcon PHP for our website MVC Framework.
I am trying to test my all models and Controllers code using KAHLAN.

When I am trying to stub phalcon's Functions (FINDFIRST, GetRelated etc) it is not working.

I even put the API Patcher code in my kahlan-config.php which is given in

http://kahlan.readthedocs.org/en/latest/integration/#working-with-a-autoloader-not-compatible-with-psr-0

PATCHER CODE IN kahlan-config.php

Filter::register('api.patchers', function($chain) {
$interceptor = Interceptor::instance();
$patchers = $interceptor->patchers();
$patchers->add('layer', new Kahlan\Jit\Patcher\Layer([
'override' => [
'Phalcon\Mvc\Model'
]
]));
return $chain->next();
});

Filter::apply($this, 'patchers', 'api.patchers');

PFA my model and test files.

@m1ome
Copy link
Collaborator Author

m1ome commented Mar 30, 2016

@shivshankarsomu you need multiple steps for testing Phalcon.
First of all you need to load your models to PSR4-autoloader:

Filter::register('app.namespaces', function($chain) {
  $this->_autoloader->addPsr4('Api\\Models\\', __DIR__ . '/app/models/');
  $this->_autoloader->addPsr4('Api\\Controllers\\V1\\', __DIR__ . '/app/controllers/v1/');
});

In e.g. we loading here models & controllers from directories, moving them to namespaces.

Second, you should add a Layer to be able to Stub/Mock Phalcon C-extension:

Filter::register('app.patchers', function($chain) {
    $interceptor = Interceptor::instance();
    $patchers = $interceptor->patchers();
    $patchers->add('layer', new Layer([
        'override' => [
            'Phalcon\Mvc\Model'
        ]
    ]));

    return $chain->next();
});

Third you should be CORRECT when passing parameters to stubbed method:

Stub::on('Api\Models\Cards')->method('::findFirst', function($params = null) {
  $card = new stdClass();
  $card->active = 1;

  return $card;
});

As you see i am providing function($params = null) and in your files you don't do such thing. For Stub system it looks like method will be different from ::findFirst that uses Phalcon.

@shivshankarsomu
Copy link

@m1ome Thanks for the reply

I changed the code to this then also it is not working
$match_model = new Match();
$match_model->id = "2214";

        Stub::on('Match Model')->method('::findFirst', function($params = null) {
        return $match_model;
    });
    $series_model = new Series();
    $series_model->id = "2223";
    $series_model->series_type = "WC";
    expect($series_model->func())->toBe($match_model);

Please help me with this

@m1ome
Copy link
Collaborator Author

m1ome commented Mar 30, 2016

@shivshankarsomu do you loading models like in my first step?

@shivshankarsomu
Copy link

@m1ome yes

PFB the code.

Filter::register('app.namespace', function($chain) {
    $this->autoloader()->addPsr4('Model Layer\\' ,__DIR__ . 'db/');
    $this->autoloader()->addPsr4('helpers Layer\\' ,__DIR__ . 'helpers/');
    $this->autoloader()->addPsr4('Controllers Layer\\', __DIR__ . 'controllers/');
});

 Filter::register('api.patchers', function($chain) {
    $interceptor = Interceptor::instance();
       $patchers = $interceptor->patchers();
       $patchers->add('layer', new Kahlan\Jit\Patcher\Layer([
           'override' => [
               'Phalcon\Mvc\Model'
           ]
       ]));
       return $chain->next();
});
Filter::apply($this, 'patchers', 'api.patchers');
Filter::apply($this, 'namespaces', 'app.namespace');

Its not working yet

@jails
Copy link
Contributor

jails commented Mar 30, 2016

Can you please create a github repo with your code sample so we can clone it ? It'll be easier for us to get the issue by playing with your code.

@shivshankarsomu
Copy link

@jails @@m1ome

I had some configuration issue while mocking Phalcon ::findFirst which got fixed.

But now I am facing some issue while mocking Phalcon getRelated can you please share some examples of mocking Phalcon getRelated

@m1ome
Copy link
Collaborator Author

m1ome commented Mar 31, 2016

@m1ome
Copy link
Collaborator Author

m1ome commented Mar 31, 2016

Your stub should look like this:

$cards = Api\Models\Cards::findFirst();
Stub::on($cards)->method('getRelated', function($alias, $arguments = null) {
  $card = new stdClass();
  $card->active = 1;

  return $card;
});

@shivshankarsomu
Copy link

Thanks for the help @m1ome @jails
It worked.

@m1ome
Copy link
Collaborator Author

m1ome commented Mar 31, 2016

@shivshankarsomu you are welcome. Next time please use another issue to ask a question. Feel free to do it.

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

No branches or pull requests

3 participants