简体   繁体   English

Laravel部分模拟模型未调用

[英]Laravel partial mocked model not invoked

I'm using laravel (4.2) framework to develop a web application (PHP 5.4.25). 我正在使用laravel(4.2)框架来开发Web应用程序(PHP 5.4.25)。 I've create a repository-interface that was implemented with eloquent-repository, I use that repository inside a UserController: 我已经创建了一个用eloquent-repository实现的存储库接口,我在UserController中使用了该存储库:

#   app/controllers/UsersController.php

use Gas\Storage\User\UserRepositoryInterface as User;

class UsersController extends \BaseController {
    protected $user;

    public function __construct(User $user) {
        $this->user = $user;

    }

    public function store() {
        $input = Input::all();
        $validator = Validator::make(Input::all(), $this->user->getRoles());

        if ( $validator->passes() ) {
            $this->user->getUser()->username = Input::get('username');
            $this->user->getUser()->password = Hash::make(Input::get('password'));
            $this->user->getUser()->first_name = Input::get('first_name');
            $this->user->getUser()->last_name = Input::get('last_name');
            $this->user->getUser()->email = Input::get('email');
            $this->user->save();


            return false;
        } else {
            return true;
        }
    }
}

My Repository implementation: 我的存储库实现:

namespace Gas\Storage\User;

#   app/lib/Gas/Storage/User/EloquentUserRepository.php

use User;

class EloquentUserRepository implements UserRepositoryInterface {

    public $_eloquentUser;

    public function __construct(User $user) {
        $this->_eloquentUser = $user;
    }

    public function all()
    {
        return User::all();
    }

    public function find($id)
    {
        return User::find($id);
    }

    public function create($input)
    {
        return User::create($input);
    }

    public function save()
    {
        $this->_eloquentUser->save();
    }

    public function getRoles()
    {
        return User::$rules;
    }

    public function getUser()
    {
        return $this->_eloquentUser;
    }
}

I've also create a UsersControllerTest to testing the controller and all works fine, the user was added to the DB. 我还创建了一个UsersControllerTest来测试控制器,并且一切正常,将用户添加到数据库中。 After I mocked my UserRepositoryInterface because I don't need to test the DB insert, but I just want to test the controller 在嘲笑UserRepositoryInterface之后,因为我不需要测试数据库插入,但是我只想测试控制器

class UsersControllerTest extends TestCase {
    private $mock;

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

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

    public function mock($class) {
        $mock = Mockery::mock($class);

        $this->app->instance($class, $mock);

        return $mock;
    }

    public function testStore() {
        $this->mock = $this->mock('Gas\Storage\User\UserRepositoryInterface[save]');

        $this->mock
            ->shouldReceive('save')
            ->once();

        $data['username'] = 'xxxxxx';
        $data['first_name'] = 'xxxx';
        $data['last_name'] = 'xxxx';
        $data['email'] = 'prova@gmail.com';
        $data['password'] = 'password';
        $data['password_confirmation'] = 'password';

        $response = $this->call('POST', 'users', $data);

        var_dump($response->getContent());
    }
}

My ruote file: 我的ruote文件:

Route::resource('users', 'UsersController');

When I run the test I get the following error: 运行测试时,出现以下错误:

Mockery\Exception\InvalidCountException : Method save() from Mockery_0_Gas_Storage_User_UserRepositoryInterface should be called
 exactly 1 times but called 0 times.

Why the mocked method save has not be called? 为什么没有调用模拟方法保存

What is wrong? 怎么了?


EDIT: without partial mock all works fine, now the question is: why with partial mock it doesn't work? 编辑:没有部分模拟都可以正常工作,现在的问题是:为什么部分模拟不起作用?


Thanks 谢谢

Looking back at your code, it seems like you should be able to use partial mocks just by changing your mock function to something like this: 回顾一下代码,似乎只需将模拟函数更改为以下内容即可使用部分模拟:

public function mock($class) {
    $mock = Mockery::mock($class);
    $ioc_binding = preg_replace('/\[.*\]/', '', $class);
    $this->app->instance($ioc_binding, $mock);

    return $mock;
}

You are telling the mock to expect the save() method, but the save() is on the Eloquent model inside the Repository, not the Repository you are mocking. 您告诉模拟对象期望使用save()方法,但是save()位于存储库内的Eloquent模型上,而不是您要模拟的存储库上。

Your code is currently leaking details of the implementation of the Repository. 您的代码当前正在泄漏存储库实现的详细信息。

Instead of calling: 而不是调用:

$this->user->getUser()->username = Input::get('username');

You need to pass an instance of the User into the Repository: 您需要将User的实例传递到存储库中:

$this->user->add(User::create(Input::all());

Or you pass the array of Input into the Repository and allow the Repository to create a new User instance internally: 或者,您将Input数组传递到存储库中,并允许存储库在内部创建一个新的User实例:

$this->user->add(Input::all());

You would then mock the add() method in your test: 然后,您可以在测试中模拟add()方法:

$this->mock->shouldReceive('add')->once();

The comments about Laravel not being suited for mocking or unit testing are wrong. 关于Laravel不适合模拟或单元测试的评论是错误的。

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

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