2016-04-02 8 views
2

Я использую Laravel 5.2, phpunit 5.0.0 и PHP 7.0.3 и пытаюсь написать тест с взаимодействием с базой данных, касающийся метода видимости моделей Eloquent.Mocking Laravel 5.2 локальная область с phpunit и mockery

У меня есть что-то вроде этого:

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()); 
    } 
} 

я заполнения базы данных с записью изображения, где имя установлено значение «тест».

Первое, что я подумал, было то, что мне не пришлось бы издеваться над вызовом области, потому что все, что мне нужно, находится в базе данных. А поскольку (не упрощенный) код у меня работает вне теста, я думаю, что вызовы области не работают в phpunit. (Я получаю сообщение об ошибке «Попытка получить исключение без объектов»).

Хорошо, так что я пытался издеваться вызов с издевательством:

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)?

ответ

1

Я бы использовал инъекцию зависимостей вместо методов вызова в статическом виде. Так что-то вроде этого:

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)); 
} 
+0

Я использую Laravel областей запроса (https://laravel.com/docs/5.1/eloquent#query-scopes). Как я могу назвать их не статически? –

+0

Вы можете сделать это, если используете инъекцию зависимостей, как в моем примере. Возможно, [этот пост] (https://laracasts.com/discuss/channels/general-discussion/l5-facades-or-dependency-injection) разъясняет его. Разве это не сработало для вас? –

Смежные вопросы