我正在尝试test relationships between models使用Ardent
和FactoryMuff
。我能够在belongs_to
方向测试关系,但我无法在has_many
方向测试它。
我正在测试的模型是住宅房地产租赁应用程序,它是相应的租赁历史记录。一个非常简化的数据库模式:
+--------------+
| applications |
+--------------+
| id |
| name |
| birthday |
| income |
+--------------+
+----------------+
| history |
+----------------+
| id |
| application_id |
| address |
| rent |
+----------------+
这是我的历史模型:
class History extends Ardent
{
protected $table = 'history';
public static $factory = array(
'application_id' => 'factory|Application',
'address' => 'string',
'rent' => 'string',
);
public function application()
{
return $this->belongsTo('Application');
}
}
这是我的测试,以确保历史对象属于租赁应用程序:
class HistoryTest extends TestCase
{
public function testRelationWithApplication()
{
// create a test rental history object
$history = FactoryMuff::create('History');
// make sure the foreign key matches the primary key
$this->assertEquals($history->application_id, $history->application->id);
}
}
这很好用。但是,我无法弄清楚如何在另一个方向上测试这种关系。在项目要求中,租赁应用程序必须至少有一个与之关联的租赁历史记录对象。这是我的应用程序模型:
class Application extends Ardent
{
public static $rules = array(
'name' => 'string',
'birthday' => 'call|makeDate',
'income' => 'string',
);
public function history()
{
return $this->hasMany('History');
}
public static function makeDate()
{
$faker = \Faker\Factory::create();
return $faker->date;
}
}
这就是我试图测试has_many
关系的方式:
class ApplicationTest extends TestCase
{
public function testRelationWithHistory()
{
// create a test rental application object
$application = FactoryMuff::create('Application');
// make sure the foreign key matches the primary key
$this->assertEquals($application->id, $application->history->application_id);
}
}
当我运行单元测试时,这会导致ErrorException: Undefined property: Illuminate\Database\Eloquent\Collection::$application_id
。对于我,这说得通。我告诉FactoryMuff
无处创建至少一个相应的History
对象以与我的Application
对象一起使用。我也没有编写任何代码来强制要求Application
对象必须至少有一个History
对象。
application
对象必须至少有一个history
对象”?has_many
方向?答案 0 :(得分:1)
是的,您应该始终在两个方向上测试关系,因为您可能需要分别从两端访问每个模型。
至于强制执行,没有我所知道的编程方式,当你使用has()方法调用模型时,你必须内联:
$application = Application::find($id)->has('history', '>=', 1)->get();
现在hasMany()关系将返回一个集合,因此您实际上是在尝试访问Collection实例上的application_id属性。
你有两个选择来测试它,第一个是循环和assertEquals,如下所示:
foreach($application->history as $history) {
$this->assertEquals($application->id, $history->application_id);
}
现在,既然您正在测试,并且创建的模型的实例是出于测试目的,那么可能值得做类似以下的事情:
$history = $application->history->first();
$this->assertEquals($application->id, $history->application_id);
重申一下,问题是如果找到子关系,hasMany()关系将始终返回Illuminate \ Database \ Eloquent \ Collection的实例,即使只有一个,但上述两种方法应该足以满足您的要求需要。希望有所帮助。
P.S:我的示例不包括验证以确保变量不为空等等,可能值得将其添加到您的测试中。
- 更新 -
不幸的是,我不熟悉FactoryMuff,虽然如果它以我认为的方式工作,你应该能够在你的测试中做到以下几点:
$application = FactoryMuff::create('Application');
$history = FactoryMuff::create('History');
$application->history()->save($history);
如果你指的是实际的应用程序代码,你可以直接进入模型事件并添加一个新的History对象。