【发布时间】:2015-06-25 06:49:07
【问题描述】:
我正在尝试编写一个测试用例,用于测试 Laravel 4.2 中两个 Eloquent 模型之间关系的关联和分离
这是我的测试用例:
class BookingStatusSchemaTest extends TestCase
{
private $statusText = "Confirmed";
private $bookingStub;
private $statusStub;
public function testMigrateService()
{
$this->createTestData();
$booking = $this->bookingStub;
$status = $this->statusStub;
/**
* Check that the booking has no status. OK
*/
$this->assertNull($booking->status);
/**
* Check that status has no booking. OK
*/
$this->assertEquals(count($status->bookings), 0);
/**
* Add a status to the booking. OK
*/
$booking->status()->associate($this->statusStub);
/**
* Check that status has a booking. NOT OK - This gives error
*/
$this->assertEquals(count($status->bookings), 1);
/**
* Check that the booking has a status. OK
*/
$this->assertNotNull($booking->status);
/**
* Do NOT delete the status, just set the reference
* to it to null.
*/
$booking->status = null;
/**
* And check again. OK
*/
$this->assertNull($booking->status);
}
private function createTestData()
{
$bookingStatus = BookingStatus::create([
'status' => $this->statusText
]);
$booking = Booking::create([ ]);
$this->bookingStub = $booking;
$this->statusStub = $bookingStatus;
}
}
当我执行它时,我得到:
There was 1 failure:
1) BookingStatusSchemaTest::testMigrateService
Failed asserting that 1 matches expected 0.
预订模式:
class Booking extends Eloquent {
/**
* A booking have a status
*/
public function status()
{
return $this->belongsTo('BookingStatus');
}
}
BookingStatus 模型:
class BookingStatus extends Eloquent
{
protected $table = 'booking_statuses';
protected $guarded = [ 'id' ];
protected $fillable = ['status'];
/**
* A booking status belongs to a booking
*/
public function bookings()
{
return $this->hasMany('Booking');
}
}
这是预订状态的迁移架构:
Schema::create('booking_statuses', function(Blueprint $table)
{
$table->increments('id');
$table->string('status');
$table->timestamps();
});
这里是预订:
Schema::create('bookings', function(Blueprint $table)
{
$table->increments('id');
$table->unsignedInteger('booking_status_id')->nullable();
$table->timestamps();
});
我必须添加/更改什么才能验证我的测试用例中的关系?
【问题讨论】:
-
这是因为
$testBooking->status永远不会为空,它是一个Illuminate\Support\Collection - 这就是您将关系 作为属性访问时所得到的。集合永远不会为空,但它可以为空,您可以使用$testBooking->status->isEmpty()(返回布尔值)进行检查,或者将其视为数组:$this->assertCount(0, $testBooking->status);。 -
但是
echo $testBooking->status->status;给了Confirmed,所以我认为它没有被删除.. -
好吧,确实有点奇怪。我注意到的另一件事:在您的
createTestData中,您似乎希望从save()-方法返回 id - 事实并非如此,save()返回一个布尔值,指示一切是否正常。在您的情况下,它还没有爆炸,因为布尔值可能在find()-method 中被强制转换为 1。您能否在测试方法中使用var_dump($this->bookingId, $this->statusId)进行检查。不确定这是否是罪魁祸首,但无论如何你都应该修复它。这有什么改变吗? -
实际上,仔细观察后,您的数据库设计似乎有点偏离。
bookings-table 应该包含外部键 'booking_status_id' 并且绝对应该 not 级联删除 - 如果您删除预订,您不想删除相关状态,因为其他预订可能是与该状态相关联。所以:BookingbelongsToBookingStatus和BookingStatushasManyBooking(belongsToMany可能听起来更自然,但那是多对多-关系)。 -
那是因为您仍在使用在
createTestData()方法中创建的实例。他们当时加载了这些属性。 1.) 关联状态后,您必须save()预订以保持更改。 2.) 您必须“重新加载”(即获取新实例)您的$status,例如使用$status = BookingStatus::first();获取预订,或者至少触发一个新查询来获取预订:$status->load('bookings');或$status->bookings()->get()。 3.) 你(希望)永远不会在实际应用程序中做这样的事情!
标签: laravel laravel-4 phpunit eloquent