Laravel控制器单元测试未调用的模拟模型

时间:2014-04-17 16:08:33

标签: php unit-testing laravel-4 mockery

我正在尝试测试控制器操作。该动作应调用模型上的函数,返回模型。在测试中,我模拟了模型,将其绑定到IoC容器。我通过其构造函数将依赖项注入控制器。然而,不知何故,模拟没有被发现和调用,而是正在调用模型的实时版本。 (我可以说,正在生成日志。)

首先,我的单元测试。创建模拟,告诉它期望一个函数,将它添加到IoC容器,调用路由。

public function testHash(){
    $hash = Mockery::mock('HashLogin');
    $hash->shouldReceive('checkHash')->once();

    $this->app->instance('HashLogin', $hash);

    $this->call('GET', 'login/hash/c3e144adfe8133343b37d0d95f987d87b2d87a24');
}

其次,我的控制器构造函数注入依赖项。

public function __construct(User $user, HashLogin $hashlogin){
    $this->user = $user;
    $this->hashlogin = $hashlogin;
    $this->ip_direct = array_key_exists("REMOTE_ADDR",$_SERVER) ? $_SERVER["REMOTE_ADDR"] : null;
    $this->ip_elb = array_key_exists("HTTP_X_FORWARDED_FOR",$_SERVER) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : null;

    $this->beforeFilter(function()
    {
        if(Auth::check()){return Redirect::to('/');}
    });
}

然后我的控制器方法。

public function getHash($code){
    $hash = $this->hashlogin->checkHash($code);
    if(!$hash){
        return $this->badLogin('Invalid Login');
    }
    $user = $this->user->getFromLegacy($hash->getLegacyUser());
    $hash->cleanup();
    $this->login($user);
    return Redirect::intended('/');
}

正确调用控制器方法,但似乎没有看到我的Mock,所以它调用了实际模型的函数。这导致模拟的期望失败,并且在对DB的检查中是不可取的。

我在另一个测试中也遇到了同样的问题,尽管这个问题使用了Laravel内置的外墙。

测试:

public function testLoginSuccessfulWithAuthTrue(){
    Input::shouldReceive('get')->with('username')->once()->andReturn('user');
    Input::shouldReceive('get')->with('password')->once()->andReturn('1234');
    Auth::shouldReceive('attempt')->once()->andReturn(true);
    $user = Mockery::mock('User');
    $user->shouldReceive('buildRBAC')->once();
    Auth::shouldReceive('user')->once()->andReturn($user);

    $this->call('POST', 'login');

    $this->assertRedirectedToRoute('index');
}

控制器方法:

public function postIndex(){
    $username = Input::get("username");
    $pass = Input::get('password');
    if(Auth::attempt(array('username' => $username, 'password' => $pass))){
        Auth::user()->buildRBAC();
    }else{
        $user = $this->user->checkForLegacyUser($username);
        if($user){
            $this->login($user);
        }else{
            return Redirect::back()->withInput()->with('error', "Invalid credentials.");
        }
    }
    return Redirect::intended('/');
}

我收到错误:

Mockery\Exception\InvalidCountException: Method get("username") from Mockery_5_Illuminate_Http_Request should be called exactly 1 times but called 0 times."

同样,我知道该方法被正确调用,似乎没有使用模拟。

1 个答案:

答案 0 :(得分:4)

解决了它。我曾尝试在一个地方或另一个地方使用命名空间,但显然Mockery::mockapp->instance()都需要完全命名空间的名称。在其他测试中我没有遇到过这个问题,所以我甚至都没有考虑过。我希望这可以帮助别人,因为这个让我的大脑搁浅了一段时间。

相关代码已修复:

$hash = Mockery::mock('App\Models\Eloquent\HashLogin');
$this->app->instance('App\Models\Eloquent\HashLogin', $hash);