Php Laravel 5-使用模拟来模拟雄辩的模型
我在网上到处找,但似乎找不到我问题的答案。我一直在潜心使用PHPUnit和mockry测试Laravel中的控制器。然而,我似乎并没有正确地嘲笑我雄辩的模型。我确实以同样的方式模拟了我的Auth::user(),尽管在下面的测试中没有使用它 AddressController中需要测试的功能:Php Laravel 5-使用模拟来模拟雄辩的模型,php,unit-testing,laravel,eloquent,mockery,Php,Unit Testing,Laravel,Eloquent,Mockery,我在网上到处找,但似乎找不到我问题的答案。我一直在潜心使用PHPUnit和mockry测试Laravel中的控制器。然而,我似乎并没有正确地嘲笑我雄辩的模型。我确实以同样的方式模拟了我的Auth::user(),尽管在下面的测试中没有使用它 AddressController中需要测试的功能: public function edit($id) { $user = Auth::user(); $company = Company::where('kvk', $user->k
public function edit($id)
{
$user = Auth::user();
$company = Company::where('kvk', $user->kvk)->first();
$address = Address::whereId($id)->first();
if(is_null($address)) {
return abort(404);
}
return view('pages.address.update')
->with(compact('address'));
}
包含设置和模拟方法的ControllerTest
abstract class ControllerTest extends TestCase
{
/**
* @var \App\Http\Controllers\Controller
*/
protected $_controller;
public function setUp(){
parent::setUp();
$this->createApplication();
}
public function tearDown()
{
parent::tearDown();
Mockery::close();
}
protected function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
}
AddressControllerTest扩展ControllerTest
class AddressControllerTest extends ControllerTest
{
/**
* @var \App\Models\Address
*/
private $_address;
/**
* @var \App\Http\Controllers\AddressController
*/
protected $_controller;
public function setUp(){
parent::setUp();
$this->_controller = new AddressController();
$this->_address = factory(Address::class)->make();
}
public function testEdit404(){
$companyMock = $this->mock(Company::class);
$companyMock
->shouldReceive('where')
->with('kvk', Mockery::any())
->once();
->andReturn(factory(Company::class)->make([
'address_id' => $this->_address->id
]));
$addressMock = $this->mock(Address::class);
$addressMock
->shouldReceive('whereId')
->with($this->_address->id)
->once();
->andReturn(null);
//First try to go to route with non existing address
$this->action('GET', 'AddressController@edit', ['id' => $this->_address->id]);
$this->assertResponseStatus(404);
}
}
它不断抛出的错误是:
1) AddressControllerTest::testEdit404
Mockery\Exception\InvalidCountException: Method where("kvk", object(Mockery\Matcher\Any)) from Mockery_1_Genta_Models_Company should be called exactly 1 times but called 0 times.
也许有人有什么想法?好吧,在找到Jeffrey Way(Laracasts背后的人)的多篇帖子后,他建议人们停止模仿有说服力的对象,而是使用内存数据库,我尝试了这种方法。我认为这可能对将来有同样问题的其他用户非常有用,所以我将在下面解释 现在,我已经使用sqlite编辑了我的'config/database.php'文件,以支持内存中的数据库选项:
'sqlite' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
接下来,在文件顶部,您将看到以下配置:
'default' => env('DB_CONNECTION', 'mysql'),
这可以保持不变,这意味着Laravel将检查您的.env变量以找到“DB_连接”,或者使用mysql作为默认值。这可能是您在正常运行应用程序时希望执行的操作。但是,在进行测试时,您希望覆盖此配置,并将数据库配置临时设置为“sqlite”。这可以通过将“DB_CONNECTION”变量添加到.env文件中来实现:
DB_CONNECTION=mysql
最后,在您的phpunit.xml(Laravel用于实例化单元测试的配置文件)中,您必须告诉您,在测试此变量时,应将其设置为“sqlite”:
<env name="DB_CONNECTION" value="sqlite"/>
它会告诉Laravel在开始测试之前运行数据库迁移,这样您就可以像平常一样使用这些表
这样对我来说非常合适!希望你们能使用它。在检查我的控制器方法是否被调用以及替换后是否被调用时,将$this->call()方法替换为$this->action()方法。但是问题仍然存在。对我来说很好。谢谢我还在迁移后为DB设置种子。需要注意的是:您会发现
@dependens testCreateCard
表示法无法将Id从一个方法传递到另一个方法,因为setUp()
在每个测试中运行一次,每次都会重置DB。我用硬编码的值解决了这个问题。
use \Illuminate\Foundation\Testing\DatabaseMigrations;