dopuzf0898 2016-05-11 10:43
浏览 68
已采纳

Mockey / Laravel与Authorizer :: getResourceOwnerId的静态调用

I am attempting to use Mockery to fully test some features of a Laravel 5.1 codebase.

I've not done a huge amount of unit testing in Mockery, and certainly not a huge amount with static calls... of which Laravel uses plenty.

I am aware that testing static calls is horrible.. but it can be done. In what I consider good practice (please feel free to correct me), I am attempting to mock these classes to increase separation of tested components.

I am using the \Mockery::mock('alias:{classname}') feature in order to catch these static calls.

For example, to check the current logged in user, the id is found using:

$user_id = (int)Authorizer::getResourceOwnerId();

However, the testing features seem to have some limitations, and I could be using them wrong - the exact question follows below:

Testing structure

My current situation is as follows:

class AuthRoutesTest extends TestCase {

// ...

protected $mock_authorizer;

// ...

public function setUp()
{
    parent::setUp();

    // ...

    $this->mock_authorizer
        ->shouldReceive('getResourceOwnerId')
        ->andReturnValues(
            [null, 3, 3, 3]
        );
}

public function tearDown()
{
    \Mockery::close();
}

Now the tests - all of these require $user_id = (int)Authorizer::getResourceOwnerId(); to return values.

public function testFirst() {
    // $user_id is null, then 3, 3 finally 3
}

And here's the problem:

I want to have.. lets say testSecond() with a separate set of values: say [1,2,null,4].

Each test seems to reset the array (go back to the beginning).

Note: -

  • I have tried to call ->shouldReceive('getResourceOwnerId') again - this does not help
  • I have tried to append the next values to the array, but it starts again at key 0

Is this possible, and if so, how is this done?

(I am aware there are other ways of coding a site.. this is more about testing existing code and avoiding the re-write - at least for now)

  • 写回答

1条回答 默认 最新

  • donglian8407 2016-05-17 09:58
    关注

    If you add byDefault() to your expectation it's possible to override the expectation after it's initiated in the setUp() method.

    You would do something like this:

    public function setUp()
    {
        parent::setUp();
    
        // ...
    
        $this->mock_authorizer
            ->shouldReceive('getResourceOwnerId')
            ->andReturnValues(
                [null, 3, 3, 3]
            )->byDefault();
    }
    

    Then in your second test case it's then possible to override the expectation you defined in the setUp method like this:

    public function testSecond() {
        $this->mock_authorizer
            ->shouldReceive('getResourceOwnerId')
            ->andReturnValues(
                [1,2,null,4]
            );
    }
    

    This post: Override Mockery return values might also be useful.

    You can also read about expectations and the byDefault() method in the Mockery docs.

    Also, I would suggest that you create a facade or use dependency injection for the Authorizer class instead of creating an instance mock, (using Mockery alias) since instance mocks might affect tests in other classes and thereby result in unwanted issues.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度