【问题标题】:Mocking Laravel 5.2 local scope with phpunit and Mockery使用 phpunit 和 Mockery 模拟 Laravel 5.2 本地范围
【发布时间】:2016-07-22 08:53:06
【问题描述】:

我正在使用 Laravel 5.2、phpunit 5.0.0 和 PHP 7.0.3,并尝试编写一个涉及 Eloquent 模型范围方法的数据库交互测试。

我有一个类似的东西:

class Picture extends Illuminate\Database\Eloquent\Model {
    ...
    public function scopeGetPictureNameById($oQuery, $pictureHId) {
         return $oQuery->select('name')->where('h_id', '=',   $pictureHId)->first()->name;
    }
}

class someHelperClass {
    public function someMethod($pictureId) {
        $pictureName = Picture::getPictureNameById($pictureId);
        return "name is " . $pictureName;
    }
}


class SomeTest extends TestCase {

    use DatabaseMigrations;

    protected $someHelper;

    public function setUp() {
        parent::setUp();
        $this->someHelper = new SomeHelper();
    }

    /**
     * @test
     */
    public function someMethodTest() {
        $expectedName = "test";
        $this->assertEquals("name is " . $expectedName, $this->someHelper->someMethod());
    }
}

我使用名称设置为“test”的图片记录为数据库播种。

我首先想到的是不必模拟范围调用,因为我只需要在数据库中。而且由于我在测试之外工作的(非简化)代码,我猜想范围调用在 phpunit 中不起作用。 (我得到一个“试图获取非对象的属性”异常)。

好的,所以我尝试用 Mockery 模拟调用:

class SomeTest extends TestCase {

    use DatabaseMigrations;

    protected $someHelper;

    public function setUp() {
        parent::setUp();
        $this->someHelper = new SomeHelper();
    }

    /**
     * @test
     */
    public function someMethodTest() {
        $expectedName = "test";

        $mockedPicture = Mockery::mock('overload:App\Models\Picture');
        $mockedPicture->shouldReceive('getPictureNameById')->andReturn('test');

        //also tried this: $mockedPicture->shouldReceive('scopeGetPictureNameById')->andReturn('test');


        $this->assertEquals("name is " . $expectedName, $this->someHelper->someMethod());
    }
}

我得到的只是“无法加载模拟 App\Models\Picture,类已经存在”。那么如何正确模拟像 Picture::getPictureNameById($pictureId) 这样的查询范围调用?

【问题讨论】:

    标签: php laravel phpunit mockery


    【解决方案1】:

    我会使用依赖注入而不是静态调用 Picture 类的方法。所以是这样的:

    class someHelperClass {
    
        protected $picture;
    
        public function __construct(Picture $picture) {
            $this->picture = $picture;
        }
    
        public function someMethod($pictureId) {
            $pictureName = $this->picture->getPictureNameById($pictureId);
            return "name is " . $pictureName;
        }
    }
    

    然后在你的测试中:

    public function someMethodTest() {
        $expectedName = "test";
    
        $mockedPicture = Mockery::mock('App\Models\Picture');
        $mockedPicture->shouldReceive('getPictureNameById')->andReturn('test');
        $someHelper = new SomeHelper($mockedPicture);
    
        $this->assertEquals("name is " . $expectedName, $someHelper->someMethod(1));
    }
    

    【讨论】:

    • 我正在使用 Laravel 查询范围 (laravel.com/docs/5.1/eloquent#query-scopes)。我怎样才能非静态地调用它们?
    • 如果你像我的例子那样使用依赖注入,你可以这样做。也许this post 澄清了这一点。它不适合你吗?
    猜你喜欢
    • 2014-11-05
    • 2016-01-14
    • 2016-08-17
    • 2014-08-24
    • 2015-03-27
    • 2022-01-04
    • 2014-03-21
    • 2021-06-23
    • 2017-08-16
    相关资源
    最近更新 更多