2

我正在尝试使用和测试模型之间的关系。我能够测试方向上的关系,但我无法在方向上测试它。ArdentFactoryMuffbelongs_tohas_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对象。

问题

  1. 如何执行“一个application对象必须至少有一个history对象”的规则?
  2. 我如何测试has_many关系的方向?
4

1 回答 1

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 的实例,但上述两种方法应该足以满足您的需求。希望有帮助。

PS:我的示例不包括验证以确保变量不为空等等,可能值得将其添加到您的测试中。

- 更新 -

不幸的是,我不熟悉 FactoryMuff,但如果它以我相信的方式工作,您应该能够在测试中执行以下操作:

$application = FactoryMuff::create('Application');
$history = FactoryMuff::create('History');
$application->history()->save($history);

如果您指的是您的实际应用程序代码,您可以直接挂接到模型事件并在那里添加一个新的 History 对象。

于 2013-12-16T23:26:01.893 回答