我有以下型号:
Grid.php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use App\Model\Rover;
class Grid extends Model
{
/**
* Table Name
*/
protected $table='grid';
public function rovers()
{
return $this->hasMany(Rover::class);
}
}
Rover.php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use App\Model\Grid;
class Rover extends Model
{
/**
* Table Name
*/
protected $table='rover';
public function grid()
{
return $this->belongsTo(Grid::class);
}
public function setGridPosXValue($value)
{
$Grid = $this->grid()->first();
$width = $Grid->width;
if($value < 0 || $value > $width){
throw new \InvalidArgumentException("X is out of grid bounds");
}
$this->attributes['x']=$value;
}
public function setGridPosYValue($value)
{
$Grid = $this->grid()->first();
$height = $Grid->height;
if($value < 0 || $value > $height){
throw new \InvalidArgumentException("Y is out of grid bounds");
}
$this->attributes['y']=$value;
}
}
我想用theese测试来测试Rover的mutator:
namespace Tests\Unit;
use Tests\TestCase;
use App\Model\Rover;
use App\Model\Grid;
use Mockery;
define("TEST_ROVEL_SUCCESS_VAL",3);
define("TEST_ROVEL_NEGATIVE_VAL",-1);
class RoverModelTest extends TestCase
{
public function testSetGridPosXValueThrowsExceptionWhenNegative(){
$this->markTestSkipped('To be implemented');
}
public function testSetGridPosXValueThrowsExceptionWhenOverWidth(){
$rover = new Rover();
$grid = new Grid();
$grid->width=5;
$grid->height=5;
$rover->grid=$grid;
$this->expectException(\InvalidArgumentException::class);
$rover->setGridPosXValue(TEST_ROVEL_NEGATIVE_VAL);
}
public function testSetGridPosXValueThorwsExceptionOnNormal(){
$rover = new Rover();
$grid = new Grid();
$grid->width=5;
$grid->height=5;
$rover->grid=$grid;
try {
$rover->setGridPosXValue(TEST_ROVEL_SUCCESS_VAL);
$this->assertEquals($rover->x,TEST_ROVEL_SUCCESS_VAL);
} catch(\Exception $e) {
$this->fail("No exception should be thrown when setting a correct value.");
}
}
}
因此,当我运行测试时,出现以下错误:
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.
SFF 3 / 3 (100%)
Time: 125 ms, Memory: 18.00 MB
There were 2 failures:
1) Tests\Unit\RoverModelTest::testSetGridPosXValueThrowsExceptionWhenOverWidth
Failed asserting that exception of type "Illuminate\Database\QueryException" matches expected exception "InvalidArgumentException". Message was: "SQLSTATE[08006] [7] FATAL: password authentication failed for user "laravel" (SQL: select * from "grid" where "grid"."id" is null limit 1)" at
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:46
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php:33
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php:182
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:918
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:943
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:399
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:325
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:657
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:624
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:333
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2124
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2112
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2598
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2113
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:521
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:505
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php:77
/var/www/html/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:23
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php:386
/var/www/html/app/Model/Rover.php:23
/var/www/html/tests/Unit/RoverModelTest.php:28
.
2) Tests\Unit\RoverModelTest::testSetGridPosXValueThorwsExceptionOnNormal
No exception should be thrown when setting a correct value.
/var/www/html/tests/Unit/RoverModelTest.php:44
FAILURES!
Tests: 3, Assertions: 2, Failures: 2, Skipped: 1.
这意味着测试命中了错误的数据库连接。
那么,如何在测试时设置“伪”数据库连接以完全不使用任何数据库?之所以这样,是因为我想做单元测试而不是集成测试,而在集成之前我还要测试dastabase连接。
在我的情况下,我希望代码不要打到db连接并测试mutator所具有的逻辑,而无需完全写入数据库。
答案 0 :(得分:1)
您使用的是$this->grid()->first()
而不是$this->grid
,这会强制使用数据库连接来获取网格。
您可以使用部分模拟来实现所需的功能:
class RoverModelTest extends TestCase
{
private $rover;
// Avoid code duplication
protected function setUp() : void {
parent::setUp();
$this->rover = $this->getMockBuilder(Rover::class)
->setMethods('grid')
->getMock();
$grid = new Grid();
$grid->width=5;
$grid->height=5;
$this->rover->expects($this->any())->method('grid')->willReturn(collect([$grid]));
}
public function testSetGridPosXValueThrowsExceptionWhenNegative(){
$this->markTestSkipped('To be implemented');
}
public function testSetGridPosXValueThrowsExceptionWhenOverWidth(){
$this->expectException(\InvalidArgumentException::class);
$this->rover->setGridPosXValue(TEST_ROVEL_NEGATIVE_VAL);
}
public function testSetGridPosXValueThorwsExceptionOnNormal(){
try {
$this->rover->setGridPosXValue(TEST_ROVEL_SUCCESS_VAL);
$this->assertEquals($this->rover->x,TEST_ROVEL_SUCCESS_VAL);
} catch(\Exception $e) {
$this->fail("No exception should be thrown when setting a correct value.");
}
}
}