php - Laravel 使用 Mockery Eloquent 模型进行模拟

标签 php laravel mocking phpunit mockery

我正在使用 laravel(4.2) 框架开发 PHP (5.4.25) 应用程序。我想用 Mockery 测试我的 UserController,所以我以这种方式安装我的 UserController:

class UsersController extends \BaseController {
    protected $user;

    public function __construct(User $user) {
        $this->user = $user;
        $this->beforeFilter('csrf', array('on'=>'post'));
    }

    public function store() {
        $validator = Validator::make(Input::all(), User::$rules);

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


            return true;
        } else {
            return false;
        }
    }

我想要模拟 Eloquent User 模型,所以我开发了我的 UsersControllerTest:

class UsersControllerTest extends TestCase {

    private $mock;

    public function __construct() {}

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

        $this->createApplication();                                                     
    }

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

        Mockery::close();
    }

    public function testStore() {
        $this->mock = Mockery::mock('Eloquent','User[save]');                                           
        $this->mock
            ->shouldReceive('save')
            ->once()
            ->andReturn('true');                                                        
        $this->app->instance('User', $this->mock);                                      

        $data['username'] = 'qwerety';
        $data['first_name'] = 'asd';
        $data['last_name'] = 'asd123';
        $data['email'] = '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e793829493a7808a868e8bc984888a" rel="noreferrer noopener nofollow">[email protected]</a>';
        $data['password'] = 'password';
        $data['password_confirmation'] = 'password';

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

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

} 

当我运行测试时,它返回此错误:

Mockery\Exception\InvalidCountException : Method save() from Mockery_0_User should be called
 exactly 1 times but called 0 times.
为什么?怎么了?

编辑:我发现了问题 - 如果我不使用模拟对象,一切正常,并且 Controller 在数据库中创建一个新用户,但是当我使用模拟输入时: all() 方法返回空数组。

-- 谢谢

最佳答案

您测试此方法的方式是在 Controller 构造函数中传递真实 Eloquent 模型的实例,而不是模拟模型。如果您想测试外观(如 documentation 中明确说明的那样),您应该直接在外观上调用 shouldReceive() 方法以对其进行模拟。

但是,由于您正在 Controller 的 store() 方法中重新定义 $this->user 变量,因此不会调用它,除非您删除硬编码实例化并使用注入(inject)的 $user

编辑:我忽略了 $this->app->instance('User', $this->mock); 行。因此,问题可能是由于在 store 方法中您直接获取一个新的类实例,而不是通过 Laravel IoC 容器。您应该通过 App::make('User'); 来获取它,而不是存储方法中的 $this->user = new User;

关于php - Laravel 使用 Mockery Eloquent 模型进行模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25782543/

相关文章:

javascript - 如何使用 laravel mix (webpack) 在全局范围内公开 js 变量?

asp.net - HttpContext最全的mock框架是什么

python - 如何在测试中为多个函数重用相同的模拟

php - 尝试模拟 PHPUnit 中的依赖项时出现“无法重新声明类”错误

javascript - Wordpress Ajax 自定义分类法

php - Apache没有html文件夹的写权限

PHP 通过在 x 个字符后的最后一个空格上剪切字符串来制作摘录

php - 导入 CSV 数据时跳过重复值

php - Laravel - 批量赋值 ||如果找到相同的唯一键,我该如何更新数据,如果数据是新的,我该如何创建

localhost - Laravel 4 不工作