Ответы пользователя по тегу Разработка через тестирование
  • Как тестировать методы, создающие объекты других классов?

    @matperez
    Разнесите создание инстанса и его использование.
    class BarFabric
    {
      public function create(array $config = [])
      {
        return new Bar($config);
      }
    }
    class Foo
    {
      protected $barFabric;
      public function __construct(BarFabric $barFabric)
      {
        $this->barFabric = $barFabric;
      }
      public function someMethod()
      {
        $bar = $this->barFabric->create();
        $bar->method1();
        $bar->method2();
        $blabla = $bar->getResult();
        //etc
      }
    }
    
    class FooTest
    {
      public function testSomeMethod()
      {
        $bar = \Mokery::mock(Bar::class);
        // ... описание поведения для мока
        $factory = \Mokery::mock(BarFactory::class);
        $factory->shouldReceive('create')->andReturn($bar);
        $foo = new Foo($factory);
        $this->assertSomething($foo);
      }
    }


    О том, как быть с ActiveQuery...

    Во первых, выносите логику запроса так же в отдельный класс. Если генерируете новую модель, Gii это может сделать и сам.
    class FooQuery extend ActiveQuery
    {
        /**
         * @inheritdoc
         * @return Foo[]|array
         */
        public function all($db = null)
        {
            return parent::all($db);
        }
    
        /**
         * @inheritdoc
         * @return Foo|array|null
         */
        public function one($db = null)
        {
            return parent::one($db);
        }
    }


    Этот объект передавайте в целевой класс так же как фабрику:
    class Bar
    {
      protected $query;
      public function __construct(FooQuery $query)
     {
        $this->query = $query;
     }
    
     public function someMethod()
     {
        $foo = $this->query->where(...)->one();
        $foo->doSomething();
     }
    }


    Ну а дальше мокайте как и в первом случае
    $queryMock = \Mockery::mock(FooQuery::class);
    $queryMock->shouldRecieve('where->one')->andReturn($fooMock);


    ActiveQuery можно мокать частично, после этого будут выполняться все родные методы, а вот сохранение в базу пропустится.
    $fooMock = \Mockery::mock(Foo::class.'[save, update]');
    $fooMock->shouldRecieve('save', 'update')->andReturn(true);


    Relations можно не подменять вообще. Они прекрасно подставляются через ActiveRecord::populateRelation().

    $foo = new Foo();
    $foo->populateRelation('bar', new Bar());
    Ответ написан
    9 комментариев
  • Как написать функциональные тесты к REST full API?

    @matperez
    REST тестировать очень легко: делаете запрос, проверяете код и тело ответа. Запрос можно делать хоть через curl, если приспичит, но лучше взять что-нибудь по удобнее. Вот например: ole.michelsen.dk/blog/testing-your-api-with-phpuni...

    Для codeception еще вот хороший модуль есть для тестирования REST codeception.com/docs/modules/REST. пользовался им, удобная штука. Codeception еще удобен тем, что из коробки может работать с базой данных codeception.com/docs/modules/Db и вы можете тут же в тесте проверять изменилась ли в базе сущность, которую вы пытались изменить через REST интерфейс.
    Ответ написан
    4 комментария