【问题标题】:Is it necessary to test relationships in both directions?是否有必要测试两个方向的关系?
【发布时间】:2014-01-04 12:16:46
【问题描述】:

我正在尝试使用ArdentFactoryMufftest relationships between models。我可以在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 对象。

问题

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

【问题讨论】:

    标签: php unit-testing laravel phpunit ardent


    【解决方案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 对象。

    【讨论】:

    • 如何告诉FactoryMuff 在创建Application 时至少创建一个对应的History 对象?我是否自己创建History 对象并将其附加到Application
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-23
    • 2015-09-22
    相关资源
    最近更新 更多