我正在使用 laravel(4.2)框架来开发Web应用程序(PHP 5.4.25)。我创建了一个使用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;
}
}
}
我的存储库实现:
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;
}
}
我还创建了一个UsersControllerTest来测试控制器,一切正常,用户被添加到数据库中。在我嘲笑 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());
}
}
我的ruote文件:
Route::resource('users', 'UsersController');
当我运行测试时,我收到以下错误:
Mockery\Exception\InvalidCountException : Method save() from Mockery_0_Gas_Storage_User_UserRepositoryInterface should be called
exactly 1 times but called 0 times.
为什么没有调用模拟方法保存?
有什么问题?
编辑:没有部分模拟所有工作正常,现在问题是:为什么部分嘲笑它不起作用?
谢谢
答案 0 :(得分:2)
回顾一下你的代码,看起来你应该能够通过将模拟函数改为这样的方式来使用部分模拟:
public function mock($class) {
$mock = Mockery::mock($class);
$ioc_binding = preg_replace('/\[.*\]/', '', $class);
$this->app->instance($ioc_binding, $mock);
return $mock;
}
答案 1 :(得分:1)
您告诉模拟器期望save()
方法,但save()
位于存储库内的Eloquent模型上,而不是您正在模拟的存储库。
您的代码目前正在泄漏存储库实施的详细信息。
而不是打电话:
$this->user->getUser()->username = Input::get('username');
您需要将User
的实例传递到存储库:
$this->user->add(User::create(Input::all());
或者将Input
数组传递到存储库并允许存储库在内部创建新的User
实例:
$this->user->add(Input::all());
然后,您将在测试中模拟add()
方法:
$this->mock->shouldReceive('add')->once();
关于Laravel不适合模拟或单元测试的评论是错误的。