PHPSpec和Laravel-如何处理双重方法未发现问题 [英] PHPSpec and Laravel - how to handle double method not found issues

查看:94
本文介绍了PHPSpec和Laravel-如何处理双重方法未发现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当涉及调用其他方法的存根时,我的规格测试似乎出现了问题.

I appear to be having issues with my spec tests when it comes to stubs that are calling other methods.

我一直在为控制器使用Laracasts的六边形"方法,以确保它仅对HTTP层负责.

I've been following Laracasts 'hexagonal' approach for my controller to ensure it is only responsible for the HTTP layer.

<?php

use Apes\Utilities\Connect;
use \OAuth;

class FacebookConnectController extends \BaseController {


    /**
     * @var $connect
     */
    protected $connect;


    /**
     * Instantiates $connect
     *
     * @param $connect
     */
    function __construct()
    {
        $this->connect = new Connect($this, OAuth::consumer('Facebook'));
    }


    /**
     * Login user with facebook
     *
     * @return void
     */
    public function initialise() {

        // TODO: Actually probably not needed as we'll control
        // whether this controller is called via a filter or similar
        if(Auth::user()) return Redirect::to('/');

        return $this->connect->loginOrCreate(Input::all());
    }


    /**
     * User authenticated, return to main game view
     * @return Response
     */
    public function facebookConnectSucceeds()
    {
        return Redirect::to('/');
    }


}

因此,在初始化路由时,我将构造一个新的Connect实例,并将$ this类的一个实例传递给我的Connect类(以用作侦听器),然后调用loginOrCreate方法.

So when the route is initialised I construct a new Connect instance and I pass an instance of $this class to my Connect class (to act as a listener) and call the loginOrCreate method.

<?php

namespace Apes\Utilities;

use Apes\Creators\Account;
use Illuminate\Database\Eloquent\Model;
use \User;
use \Auth;
use \Carbon\Carbon as Carbon;

class Connect
{

    /**
     * @var $facebookConnect
     */
    protected $facebookConnect;


    /**
     * @var $account
     */
    protected $account;


    /**
     * @var $facebookAuthorizationUri
     */
    // protected $facebookAuthorizationUri;


    /**
     * @var $listener
     */
    protected $listener;


    public function __construct($listener, $facebookConnect)
    {
        $this->listener = $listener;
        $this->facebookConnect = $facebookConnect;
        $this->account = new Account();
    }


    public function loginOrCreate($input)
    {
        // Not the focus of this test
        if(!isset($input['code'])){
            return $this->handleOtherRequests($input);
        }

        // Trying to stub this method is my main issue
        $facebookUserData = $this->getFacebookUserData($input['code']);

        $user = User::where('email', '=', $facebookUserData->email)->first();

        if(!$user){
            // Not the focus of this test
            $user = $this->createAccount($facebookUserData);
        }

        Auth::login($user, true);
        // I want to test that this method is called
        return $this->listener->facebookConnectSucceeds();

    }


    public function getFacebookUserData($code)
    {
        // I can't seem to stub this method because it's making another method call
        $token = $this->facebookConnect->requestAccessToken($code);

        return (object) json_decode($this->facebookConnect->request( '/me' ), true);
    }

    // Various other methods not relevant to this question

我试图缩小这一范围,以专注于测试中的方法以及到目前为止我对什么地方出了问题的理解.

I've tried to trim this down to focus on the methods under test and my understanding thus far as to what is going wrong.

<?php

namespace spec\Apes\Utilities;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use \Illuminate\Routing\Controllers\Controller;
use \OAuth;
use \Apes\Creators\Account;


class ConnectSpec extends ObjectBehavior
{
    function let(\FacebookConnectController $listener, \OAuth $facebookConnect, \Apes\Creators\Account $account)
    {
        $this->beConstructedWith($listener, $facebookConnect, $account);
    }


    function it_should_login_the_user($listener)
    {
        $input = ['code' => 'afacebooktoken'];

        $returnCurrentUser = (object) [
            'email' => 'existinguser@domain.tld',
        ];

        $this->getFacebookUserData($input)->willReturn($returnCurrentUser);

        $listener->facebookConnectSucceeds()->shouldBeCalled();
        $this->loginOrCreate($input);
    }

所以这是我遇到问题的规范.首先,我假装我已经有了一个Facebook令牌.然后,在失败的地方,是我需要弄弄getFacebookUserData方法将返回一个存在于我的users表中的示例用户.

So here's the spec that I'm having issues with. First I pretend that I've got a facebook token already. Then, where things are failing, is that I need to fudge that the getFacebookUserData method will return a sample user that exists in my users table.

但是,当我运行测试时,我得到:

However when I run the test I get:

Apes/Utilities/Connect                               
  37  ! it should login the user
      method `Double\Artdarek\OAuth\Facade\OAuth\P13::requestAccessToken()` not found.

我曾希望'willReturn'在我分别测试时会忽略getFacebookUserData方法中发生的一切,但这似乎不是.

I had hoped that 'willReturn' would just ignore whatever was happening in the getFacebookUserData method as I'm testing that separately, but it seems not.

关于我应该做什么的任何建议?

Any recommendations on what I should be doing?

我是否需要将所有OAuth类方法拉到自己的类中?考虑到OAuth已经是自己的类了,我可能需要这样做,这对我来说似乎很奇怪.有什么方法可以在getFacebookUserData中存根该方法吗?

Do I need to pull all of the OAuth class methods into their own class or something? It seems strange to me that I might need to do that considering OAuth is already its own class. Is there some way to stub the method in getFacebookUserData?

因此,我尝试对getFacebookUserData中调用的方法进行存根,并且更新后的规范如下所示:

So I tried stubbing the method that's being called inside getFacebookUserData and my updated spec looks like this:

function it_should_login_the_user($listener, $facebookConnect)
{
    $returnCurrentUser = (object) [
        'email' => 'existinguser@domain.tld',
    ];
    $input = ['code' => 'afacebooktoken'];

    // Try stubbing any methods that are called in getFacebookUserData
    $facebookConnect->requestAccessToken($input)->willReturn('alongstring');
    $facebookConnect->request($input)->willReturn($returnCurrentUser);

    $this->getFacebookUserData($input)->willReturn($returnCurrentUser);


    $listener->facebookConnectSucceeds()->shouldBeCalled();
    $this->loginOrCreate($input);
}

规范仍然失败,但错误已更改:

The spec still fails but the error has changed:

Apes/Utilities/Connect                               
  37  ! it should login the user
      method `Double\Artdarek\OAuth\Facade\OAuth\P13::requestAccessToken()` is not defined.

有趣的是,如果我将这些新的存根放在$ this-> getFacebookUserData存根之后,则错误是未找到"而不是未定义".显然,我不完全了解手头的内部工作原理:D

Interestingly if I place these new stubs after the $this->getFacebookUserData stub then the error is 'not found' instead of 'not defined'. Clearly I don't fully understand the inner workings at hand :D

推荐答案

我不熟悉所涉及的类,但是该错误表明没有方法Oauth :: requestAccessToken().

I'm not familiar with the classes involved but that error implies there is not method Oauth:: requestAccessToken().

预言不会让您存根不存在的方法.

Prophecy will not let you stub non-existent methods.

这篇关于PHPSpec和Laravel-如何处理双重方法未发现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆