简体   繁体   English

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

[英]Laravel Controller Unit test mocked model not called

I am trying to test a controller action. 我正在尝试测试控制器动作。 That action should call a function on a model, returning a model. 该动作应调用模型上的函数,返回模型。 In the test, I mocked the model, bound it to the IoC container. 在测试中,我模拟了模型,将其绑定到IoC容器。 I have the dependency being injected into the controller through its constructor. 我通过其构造函数将依赖项注入控制器。 Yet somehow, the mock isn't being found and called, and instead a live version of the model is being called. 然而,不知何故,模拟没有被发现和调用,而是正在调用模型的实时版本。 (I can tell, as logs are being generated.) (我可以说,正在生成日志。)

First, my unit test. 首先,我的单元测试。 Create the mock, tell it to expect a function, add it to the IoC container, call the route. 创建模拟,告诉它期望一个函数,将它添加到IoC容器,调用路由。

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

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

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

Second, my controller constructor where the dependency is injected. 其次,我的控制器构造函数注入了依赖项。

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('/');}
    });
}

And then my controller method. 然后我的控制器方法。

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('/');
}

The controller method is being called correctly, but it seems that it isn't seeing my Mock, so it's calling the actual model's function. 控制器方法被正确调用,但它似乎没有看到我的模拟,所以它调用实际模型的函数。 This results in the mock's expectations failing, and in checks against the DB that are not desirable. 这导致模拟的期望失败,并且在对DB的检查中是不可取的。

I am also getting the same problem in another test, though this one uses Laravel's built in Facades. 我在另一个测试中也遇到了同样的问题,尽管这个问题使用了Laravel内置的Facades。

The test: 考试:

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');
}

The Controller Method: 控制器方法:

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('/');
}

I am receiving the error: 我收到错误:

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

Again, I know the method is being called properly, it just seems that mocks aren't being used. 同样,我知道正确调用该方法,似乎没有使用模拟。

Solved it. 解决了它。 I had tried playing with namespacing before in one place or the other, but apparently both the Mockery::mock , and the app->instance() need fully namespaced names. 我曾尝试在一个地方或另一个地方使用命名空间,但显然Mockery::mockapp->instance()需要完全命名空间的名称。 This problem hadn't occurred for me in other tests, so I hadn't even considered it. 在其他测试中我没有遇到过这个问题,所以我甚至都没有考虑过。 I hope this helps someone else, because this one racked my brain for a while. 我希望这可以帮助别人,因为这个让我的大脑搁浅一段时间。

Relevant code fixed: 相关代码已修复:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM