а вообще видел разработчика на рельсы? и не увидишь - рельсы уйдут в небытие с теми разработчиками, которые 1х лет назад на них начали кодить.nepster писал(а):С другой стороны, очень много идей включая ar одолжили у рельсов, а я честно говоря не разу не видел не рельсы ни то, чтобы их гнобили за сильную связанность.
Наилучший способ переопределения классов в стороннем модуле
Re: Наилучший способ переопределения классов в стороннем модуле
Re: Наилучший способ переопределения классов в стороннем модуле
вчера на ютубе выложили презентацию чувака. че-то там про ддд итд. рассказывал как он вкорячивал ддд в yii. Модель запихивал в репозиторий, а внутри $repository->save($model) { $model->save(); }. Занавес.nepster писал(а): А вот с моделями нужно что-то делать. Так как 90% разработчиков делают 1 модель, 50 сценариев и всю логику туда-же и это в лучшем случае.
С моделями ничего делать не надо. От АР отказываемся и все. класс с 5 обязанностью в любой вселенной не очень хорошо.
Re: Наилучший способ переопределения классов в стороннем модуле
все верно. модель АР - это не то, что автоматически работает, т.к. в ней есть обязанности, которые могут себя непредсказуемо вести.ElisDN писал(а):Как раз об этом призадумался при подготовке своего скринкаста о тестировании. Может я перфекционист, но всё-таки... Вот о чём думал:nepster писал(а):Что касается тестирования тут у меня вопросы, зачем тестировать модели, работа которых на 100% ложится на yii.
С логикой фреймворка проблем нет. Другое дело, когда мы вмешиваем свою логику в процесс сохранения. В модели часто навешаны поведения и прочий код в beforeSave()/afterSave(). Многое работает с changedAttributes и прочим. И надо вызвать $model->save() и проверить, что все timestamps расставлены, поля отфильтрованы, файлы загружены и все счётчики и связи обновлены. В крайнем случае, чтобы элементарно найти баг, что забыли вернуть true из beforeSave() и модель не сохраняется.
Комбинаций для проверки может быть десятки. Сотни раз записывать в базу и вычищать порой долго. Можно вместо вызова save() вручную эмулировать работу фреймворка, дёргая эти методы beforeSave()/afterSave(), beforeDelete()/afterDelete() и расставлять dirtyAttributes, setIsNewRecord и прочее. Или смириться с необходимостью работы с базой. А хотелось бы для ускорения тестов просто заглушить код сохранения или удаления из БД и вызвать save() или delete(), но там в https://github.com/yiisoft/yii2/blob/50 ... d.php#L451 такой код:
И здесь начинаются пляски, что простым PHPUnit мы конкретно для этой модели статический getDb() никак не замокаем. Нужно либо искать библиотеки для мока статики (или самому возиться с рефлекшенами) чтобы как-то замокать этот getDb() или insert(), либо наследоваться от моделей и переопределять insertInternal(), либо подменять глобально весь Yii::$app->db вместе со схемами таблиц и возвращать обратно в каждом setUp()/tearDown(). Тогда и понял, что отвязать от БД или хотя бы замокать save() или delete() в ActiveRecord для тестов - весьма нетривиальная задача.Код: Выделить всё
$primaryKeys = static::getDb()->schema->insert($this->tableName(), $values))
Re: Наилучший способ переопределения классов в стороннем модуле
ElisDN писал(а): И здесь начинаются пляски, что простым PHPUnit мы конкретно для этой модели статический getDb() никак не замокаем. Нужно либо искать библиотеки для мока статики (или самому возиться с рефлекшенами) чтобы как-то замокать этот getDb() или insert(), либо наследоваться от моделей и переопределять insertInternal(), либо подменять глобально весь Yii::$app->db вместе со схемами таблиц и возвращать обратно в каждом setUp()/tearDown(). Тогда и понял, что отвязать от БД или хотя бы замокать save() или delete() в ActiveRecord для тестов - весьма нетривиальная задача.
>что простым PHPUnit
так не получится, это же не независимый пакет, думаю адекватный пример https://github.com/yii2tech/ar-linkmany ... se.php#L34
Код: Выделить всё
public $appConfig = [
'components' => [
'db' => $this->mock(....),
],
];
я бы мокал те методы которые завязаны на db, innerInsert, innerUpdate а то и "глубже", можно просто проверять что на innerUpdate идут "ожидаемые" аттрибуты,
Код: Выделить всё
public function updateX($value)
{
$this->x = $this->x + $value;
return $this->update(true, ['x']);
}
upd http://blog.jayfields.com/2006/12/rails ... sting.html
Re: Наилучший способ переопределения классов в стороннем модуле
AR одна из основных штук Yii. Будет очень сложно от нее отказаться, так как теряется очень жирная часть возможностей yii и наверно проще поменять инструмент, чем в yii отказаться от AR.zelenin писал(а):вчера на ютубе выложили презентацию чувака. че-то там про ддд итд. рассказывал как он вкорячивал ддд в yii. Модель запихивал в репозиторий, а внутри $repository->save($model) { $model->save(); }. Занавес.nepster писал(а): А вот с моделями нужно что-то делать. Так как 90% разработчиков делают 1 модель, 50 сценариев и всю логику туда-же и это в лучшем случае.
С моделями ничего делать не надо. От АР отказываемся и все. класс с 5 обязанностью в любой вселенной не очень хорошо.
Хотя еще вариант инкапсулировать AR и сверху налепить свой слой абстракции. Но опять таки, что проще. Сменить инструмент или шаманить ?
Re: Наилучший способ переопределения классов в стороннем модуле
отказаться от нее проще простого.nepster писал(а):AR одна из основных штук Yii. Будет очень сложно от нее отказаться, так как теряется очень жирная часть возможностей yii и наверно проще поменять инструмент, чем в yii отказаться от AR.zelenin писал(а):вчера на ютубе выложили презентацию чувака. че-то там про ддд итд. рассказывал как он вкорячивал ддд в yii. Модель запихивал в репозиторий, а внутри $repository->save($model) { $model->save(); }. Занавес.nepster писал(а): А вот с моделями нужно что-то делать. Так как 90% разработчиков делают 1 модель, 50 сценариев и всю логику туда-же и это в лучшем случае.
С моделями ничего делать не надо. От АР отказываемся и все. класс с 5 обязанностью в любой вселенной не очень хорошо.
Хотя еще вариант инкапсулировать AR и сверху налепить свой слой абстракции. Но опять таки, что проще. Сменить инструмент или шаманить ?
В АР уже все инкапсулировано. еще что-то хочешь туда запихнуть?
Re: Наилучший способ переопределения классов в стороннем модуле
В ContactFormTest валидация им замокана. Но оно не работает со статическими и непубличными методами.lynicidn писал(а):>что простым PHPUnit
так не получится, это же не независимый пакет
Тот код как раз из метода insertInternal(). Как Вы его подмените?lynicidn писал(а):я бы мокал те методы которые завязаны на db, innerInsert, innerUpdate а то и "глубже", можно просто проверять что на innerUpdate идут "ожидаемые" аттрибуты,
Нам нужно протестировать правильность работы методов beforeX()/afterX() в связке, а не валидации.lynicidn писал(а):но опять же, если считать, что валидная модель обязана сохраниться, то все тестирование скатывается до валидации, это в случае фанатизма по сценариям
И как это применить в PHP?lynicidn писал(а):upd http://blog.jayfields.com/2006/12/rails ... sting.html
Re: Наилучший способ переопределения классов в стороннем модуле
можно легко костыльнуть, чтобы потом безболезнено переехать, примерно такnepster писал(а):AR одна из основных штук Yii. Будет очень сложно от нее отказаться, так как теряется очень жирная часть возможностей yii и наверно проще поменять инструмент, чем в yii отказаться от AR.zelenin писал(а):вчера на ютубе выложили презентацию чувака. че-то там про ддд итд. рассказывал как он вкорячивал ддд в yii. Модель запихивал в репозиторий, а внутри $repository->save($model) { $model->save(); }. Занавес.nepster писал(а): А вот с моделями нужно что-то делать. Так как 90% разработчиков делают 1 модель, 50 сценариев и всю логику туда-же и это в лучшем случае.
С моделями ничего делать не надо. От АР отказываемся и все. класс с 5 обязанностью в любой вселенной не очень хорошо.
Хотя еще вариант инкапсулировать AR и сверху налепить свой слой абстракции. Но опять таки, что проще. Сменить инструмент или шаманить ?
Код: Выделить всё
class UserFinder extends Component
{
public $modelClass;
public $queryClass;
public function createQuery() { return new $this->queryClass($this->modelClass)}
public function createModel() {}
public function findXxx() {}
}
class Ar extends ActiveRecord
{
public static function instantiate($row)
{
return Yii::$app->get('userFinder')->createModel();
}
public static function find()
{
return Yii::$app->get('userFinder')->createQuery();
}
}
Re: Наилучший способ переопределения классов в стороннем модуле
про какие статические методы идет речь?ElisDN писал(а):В ContactFormTest валидация им замокана. Но оно не работает со статическими и непубличными методами.lynicidn писал(а):>что простым PHPUnit
так не получится, это же не независимый пакет
не понимаю сути проблемы $mock = $this->getMock('AR', array('insertInternal'));ElisDN писал(а):Тот код как раз из метода insertInternal(). Как Вы его подмените?lynicidn писал(а):я бы мокал те методы которые завязаны на db, innerInsert, innerUpdate а то и "глубже", можно просто проверять что на innerUpdate идут "ожидаемые" аттрибуты,
мы возвращаемся опять к проблеме их перекрытия или тестирования метода beforeSave ? $mock->exactly() конкретный пример я бы запросил, но времени не будет вам писать тест, но проблемы все вымышленные у васElisDN писал(а):Нам нужно протестировать правильность работы методов beforeX()/afterX() в связке, а не валидации.lynicidn писал(а):но опять же, если считать, что валидная модель обязана сохраниться, то все тестирование скатывается до валидации, это в случае фанатизма по сценариям
а это вы сравниваете с рельсами, вот и смотрите что тестируют в рельсках, конечно статейка так себе, но инфы в гугле мало по тестированию арElisDN писал(а):И как это применить в PHP?lynicidn писал(а):upd http://blog.jayfields.com/2006/12/rails ... sting.html
Re: Наилучший способ переопределения классов в стороннем модуле
Куда переехать? На MongoDB или Redis?lynicidn писал(а):можно легко костыльнуть, чтобы потом безболезнено переехать
Re: Наилучший способ переопределения классов в стороннем модуле
на какой нить репозиторий + дата мапперElisDN писал(а):Куда переехать? На MongoDB или Redis?lynicidn писал(а):можно легко костыльнуть, чтобы потом безболезнено переехать
http://www.design-pattern.ru/
Re: Наилучший способ переопределения классов в стороннем модуле
Про self::getDb()lynicidn писал(а):про какие статические методы идет речь?
1) Методы beforeSave() и afterSave() дергаются внутри insertInternal(). Можно переопределить анонимкой, но...lynicidn писал(а):не понимаю сути проблемы $mock = $this->getMock('AR', array('insertInternal'));
2) Ваш мок всё равно нерабочий, так как insertInternal() там protected.
Нужно протестировать процесс сохранения модели БЕЗ фактического сохранения её в базу.lynicidn писал(а):мы возвращаемся опять к проблеме их перекрытия или тестирования метода beforeSave ? $mock->exactly()
Я и не сомневаюсь, что не напишете. Вы по DI мне недавно два треда пустозвонили, что Yii из коробки всё может и всё-всё-всё умеет. В итоге также тихо слились.lynicidn писал(а):конкретный пример я бы запросил, но времени не будет вам писать тест, но проблемы все вымышленные у вас
Я? С рельсами?lynicidn писал(а):а это вы сравниваете с рельсами, вот и смотрите что тестируют в рельсках, конечно статейка так себе, но инфы в гугле мало по тестированию ар
Re: Наилучший способ переопределения классов в стороннем модуле
>Про self::getDb()
писал уже! где не надо юзаете контейнер, где надо теряетесь
>1) Методы beforeSave() и afterSave() дергаются внутри insertInternal(). Можно переопределить анонимкой, но...
не понял опять смысла анонимки
>2) Ваш мок всё равно нерабочий, так как insertInternal() там protected.
от вас чтото скрыли
>Нужно протестировать процесс сохранения модели БЕЗ фактического сохранения её в базу.
до сейв дошло - значит тру, глубже можно оперделять вплоть до аттрибутов, тоже проходили выше
>Я и не сомневаюсь, что не напишете. Вы по DI мне недавно два треда пустозвонили, что Yii из коробки всё может и всё-всё-всё умеет. В итоге также тихо слились.
no comments, пруф, может потерял
>Я? С рельсами?
ссылка была вам только адресована или у нас дебаты?
писал уже! где не надо юзаете контейнер, где надо теряетесь
>1) Методы beforeSave() и afterSave() дергаются внутри insertInternal(). Можно переопределить анонимкой, но...
не понял опять смысла анонимки
>2) Ваш мок всё равно нерабочий, так как insertInternal() там protected.
от вас чтото скрыли
>Нужно протестировать процесс сохранения модели БЕЗ фактического сохранения её в базу.
до сейв дошло - значит тру, глубже можно оперделять вплоть до аттрибутов, тоже проходили выше
>Я и не сомневаюсь, что не напишете. Вы по DI мне недавно два треда пустозвонили, что Yii из коробки всё может и всё-всё-всё умеет. В итоге также тихо слились.
no comments, пруф, может потерял
>Я? С рельсами?
ссылка была вам только адресована или у нас дебаты?
Re: Наилучший способ переопределения классов в стороннем модуле
Попробовал ещё раз. Теперь работаетlynicidn писал(а):от вас чтото скрыли
Видимо за три месяца что-то изменилось. Вопрос по мокам закрыт:
Код: Выделить всё
use tests\codeception\backend\unit\TestCase;
use yii\db\ActiveRecord;
/**
* @property integer $id
* @property integer $value
*/
class User extends ActiveRecord {}
class MockARTest extends TestCase
{
public function testSchemaInsertCallbackMock()
{
$originalDb = Yii::$app->get('db');
$schema = $this->getMock('yii\db\mysql\Schema', ['insert', 'getTableSchema']);
$schema->expects($this->atLeastOnce())->method('insert')->will($this->returnValue(['id' => 15]));
$schema->expects($this->atLeastOnce())->method('getTableSchema')->will($this->returnCallback(function () {
return new yii\db\TableSchema([
'name' => 'user',
'fullName' => 'user',
'primaryKey' => ['id'],
'foreignKeys' => [],
'columns' => [
'id' => new yii\db\ColumnSchema([
'name' => 'id',
'type' => 'integer',
'phpType' => 'integer',
'dbType' => 'int(11)',
'size' => 11,
'precision' => 11,
'isPrimaryKey' => 1,
'autoIncrement' => 1,
]),
'value' => new yii\db\ColumnSchema([
'name' => 'id',
'type' => 'integer',
'phpType' => 'integer',
'dbType' => 'int(11)',
'size' => 11,
'precision' => 11,
'isPrimaryKey' => 0,
'autoIncrement' => 0,
]),
],
]);
}));
$db = $this->getMock('\yii\db\Connection', ['getSchema']);
$db->expects($this->atLeastOnce())->method('getSchema')->will($this->returnValue($schema));
$db->expects($this->never())->method('createCommand')->will($this->returnValue(null));
Yii::$app->set('db', $db);
$model = new User();
$model->value = 12;
$this->assertTrue($model->save());
$this->assertEquals(15, $model->id);
Yii::$app->set('db', $originalDb);
}
}
Последний раз редактировалось ElisDN 2016.01.21, 12:53, всего редактировалось 1 раз.
Re: Наилучший способ переопределения классов в стороннем модуле
так не пойдет, упоролся ты, а виноват получаюсь я, ты мне дай цитату, где я писал, что "уии всевсевсе может" и где я "слился" не дав тебе ответа
Re: Наилучший способ переопределения классов в стороннем модуле
и за 3 месяца это не изменилось, вы не представляете себе как устроен и как работает мок, что у него внутри, за счет чего он достигает переопределения и прочие такие мелочи. Есть такое понятие хватать вершки...
Re: Наилучший способ переопределения классов в стороннем модуле
viewtopic.php?f=19&t=34676&p=176832#p176815lynicidn писал(а):ты мне дай цитату, где я писал, что "уии всевсевсе может" и где я "слился" не дав тебе ответа
viewtopic.php?f=26&t=34859&start=40#p177396
Re: Наилучший способ переопределения классов в стороннем модуле
оттуда же кстати подтред про теги сервисов - к вопросу о вершках)ElisDN писал(а):viewtopic.php?f=19&t=34676&p=176832#p176815lynicidn писал(а):ты мне дай цитату, где я писал, что "уии всевсевсе может" и где я "слился" не дав тебе ответа
viewtopic.php?f=26&t=34859&start=40#p177396
Re: Наилучший способ переопределения классов в стороннем модуле
если я пишу, что "yii так не может" или это не "yii подход" или еще какието "костыли" и объявляю их онными - это не означает, что я имел ввиду, что уии все может, вообще не вижу здесь логикиElisDN писал(а):viewtopic.php?f=19&t=34676&p=176832#p176815lynicidn писал(а):ты мне дай цитату, где я писал, что "уии всевсевсе может" и где я "слился" не дав тебе ответа
viewtopic.php?f=26&t=34859&start=40#p177396
ссылок можно много накидать, за слова надо отвечать более конструктивно, а не "сливаться"
Re: Наилучший способ переопределения классов в стороннем модуле
я все равно не понял твой тред про теги, теггируют схожие реализации, чтобы потом им можно было чтото скармливать, я не применял их на практике, только не понял откуда выводы про "вершки" - как раз для чего теги нужны я знаюzelenin писал(а):оттуда же кстати подтред про теги сервисов - к вопросу о вершках)ElisDN писал(а):viewtopic.php?f=19&t=34676&p=176832#p176815lynicidn писал(а):ты мне дай цитату, где я писал, что "уии всевсевсе может" и где я "слился" не дав тебе ответа
viewtopic.php?f=26&t=34859&start=40#p177396