我正在使用 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'] = 'test@gmail.com';
$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.
为什么呢?怎么了?
编辑:我发现问题 - 如果我不使用模拟对象一切正常,控制器在数据库中创建一个新用户,但是当我使用模拟时{{1 }}方法返回空数组。
- 感谢
答案 0 :(得分:1)
你在测试它的方式,在控制器构造函数中传递一个真正的Eloquent模型的实例,而不是mock。如果你想测试外墙(如documentation中明确说明的那样),你应该直接在立面上调用shouldReceive()
方法来模仿它。
但是,由于您要重新定义控制器的$this->user
方法中的store()
变量,因此除非您删除硬编码实例并使用注入的$user
,否则不会调用它。
编辑:我覆盖了$this->app->instance('User', $this->mock);
行。所以,问题可能是因为在store
方法中你直接获得了一个新的类实例,而不是通过Laravel IoC容器。您的商店方法中应该使用$this->user = new User;
而不是App::make('User');
,而应通过{{1}}
答案 1 :(得分:1)
$this->app->instance('User', $this->mock);
现在问题是你还需要通过模拟版本的User调用save()方法的模拟版本,如下所示:
$this->mock->save();
考虑以下示例:
public function testStore()
{
$input = ['name', 'Canaan'];
$this->mock
->shouldReceive('create')
->once()->with($input);
$this->app->instance('User', $this->mock);
$this->mock->create($input);
$this->call('POST', 'users', $input);
}
我希望它可以帮到你。
答案 2 :(得分:1)
问题出在$this->createApplication();
。
我评论说,行和Input::all()
适用于所有输入参数!