Я пишу несколько модульных тестов и застрял в том, что сначала считал ошибкой, но после большого разочарования кажется, что это было запланировано (но невозможно найти документацию/упоминание о) поведении/использовании.
Минимальный примерный случай выглядит так:
class UpdateListener()
{
public function handleStatusChange(UpdateUpdated $event): void
{
//checks various conditions of $event and modifies $successful_update_at
}
}
class CandidateTest extends TestCase
{
public function testSuccessfulUpdateTimestampManagement(): void
{
$updateListener = new UpdateListener();
//The first test verifies that a new timestamp is set
//when creating a mock with second argument set "true"
$updateEvent = $this->mockUpdateEvent(UpdateEvent::class, true);
$updateListener->handleStatusChange($updateEvent);
$this->assertEquals('2024-05-19', $candidate->successful_update_at->format('Y-m-d'));
//The second test sets "false" on the second argument and expects null on the attribute
$updateEvent = $this->mockUpdateEvent(UpdateEvent::class, false);
$updateListener->handleStatusChange($updateEvent);
$this->assertNull($candidate->successful_update_at);
}
private function mockUpdateEvent(string $class, bool $findsPreviousUpdate): UpdateEvent
{
$mockUpdate = \Mockery::mock(Update::class);
$mockUpdate->makePartial();
$previousSuccessfulUpdate = new Update();
$previousSuccessfulUpdate->register_date = '2024-05-19';
$mockQueryBuilder = \Mockery::mock(Builder::class);
$mockQueryBuilder->shouldReceive('getResult')->andReturn(
$findsPreviousUpdate ? $previousSuccessfulUpdate : null
);
$mockUpdate->shouldReceive('query')->andReturn($mockQueryBuilder);
return new $class($mockUpdate);
}
}
Итак, в этом минимальном примере происходит то, что я (или мне так казалось) создаю чистые макеты класса, который использует построитель запросов (laravel 11, если это имеет какое-либо значение). ), чтобы «найти» объект при определенных условиях и использовать временную метку этого объекта на макете субъекта. При некоторых условиях я ожидаю возврата null и использую этот второй флаг аргумента, чтобы сообщить макету, что он должен возвращать.
Однако именно здесь мы добираемся до «Проблемы»: второе утверждение никогда не является нулевым, макет всегда возвращает $previousSuccessfulUpdate независимо от того, что я говорю ему вернуть при создании макета.
Поэтому, посмотрев на то, что делает макеты::mock и ->andReturn, становится ясно, что под капотом происходит какое-то повторное использование макетных объектов и ожидание возврата. >
Как правильно выполнить такое утверждение на одном и том же имитируемом объекте, ожидая при этом разных результатов от имитируемых методов? Я упускаю что-то основное, что заставило бы это работать так, как я ожидаю? Разделение утверждений на разные тесты, чтобы получить своего рода «TearDown» для сброса моих макетов?
Поскольку ->andReturn, похоже, использует «очередь» возвращаемых ответов, я получаю ожидаемые утверждения, просто передавая ему различные ожидаемые возвращаемые значения в том порядке, в котором я их ожидаю. Это похоже на очень «жестко запрограммированный» способ сделать это и подразумевает, что я должен знать точный порядок и количество возвратов, которые, как я ожидаю, даст любой тест для любого макета. Я бы предпочел иметь возможность в любой момент времени точно указать, что именно должен возвращать макет, изменяя его всякий раз, когда я считаю нужным...?
$mockQueryBuilder->shouldReceive('getResult')->andReturn($previousSuccessfulUpdate, null);
Подробнее здесь: https://stackoverflow.com/questions/785 ... in-phpunit
Путаница по поводу повторного использования макета в phpunit ⇐ Php
Кемеровские программисты php общаются здесь
-
Anonymous
1716292660
Anonymous
Я пишу несколько модульных тестов и застрял в том, что сначала считал ошибкой, но после большого разочарования кажется, что это было запланировано (но невозможно найти документацию/упоминание о) поведении/использовании.
Минимальный примерный случай выглядит так:
class UpdateListener()
{
public function handleStatusChange(UpdateUpdated $event): void
{
//checks various conditions of $event and modifies $successful_update_at
}
}
class CandidateTest extends TestCase
{
public function testSuccessfulUpdateTimestampManagement(): void
{
$updateListener = new UpdateListener();
//The first test verifies that a new timestamp is set
//when creating a mock with second argument set "true"
$updateEvent = $this->mockUpdateEvent(UpdateEvent::class, true);
$updateListener->handleStatusChange($updateEvent);
$this->assertEquals('2024-05-19', $candidate->successful_update_at->format('Y-m-d'));
//The second test sets "false" on the second argument and expects null on the attribute
$updateEvent = $this->mockUpdateEvent(UpdateEvent::class, false);
$updateListener->handleStatusChange($updateEvent);
$this->assertNull($candidate->successful_update_at);
}
private function mockUpdateEvent(string $class, bool $findsPreviousUpdate): UpdateEvent
{
$mockUpdate = \Mockery::mock(Update::class);
$mockUpdate->makePartial();
$previousSuccessfulUpdate = new Update();
$previousSuccessfulUpdate->register_date = '2024-05-19';
$mockQueryBuilder = \Mockery::mock(Builder::class);
$mockQueryBuilder->shouldReceive('getResult')->andReturn(
$findsPreviousUpdate ? $previousSuccessfulUpdate : null
);
$mockUpdate->shouldReceive('query')->andReturn($mockQueryBuilder);
return new $class($mockUpdate);
}
}
Итак, в этом минимальном примере происходит то, что я (или мне так казалось) создаю чистые макеты класса, который использует построитель запросов (laravel 11, если это имеет какое-либо значение). ), чтобы «найти» объект при определенных условиях и использовать временную метку этого объекта на макете субъекта. При некоторых условиях я ожидаю возврата null и использую этот второй флаг аргумента, чтобы сообщить макету, что он должен возвращать.
Однако именно здесь мы добираемся до «Проблемы»: второе утверждение никогда не является нулевым, макет всегда возвращает $previousSuccessfulUpdate независимо от того, что я говорю ему вернуть при создании макета.
Поэтому, посмотрев на то, что делает макеты::mock и ->andReturn, становится ясно, что под капотом происходит какое-то повторное использование макетных объектов и ожидание возврата. >
Как правильно выполнить такое утверждение на одном и том же имитируемом объекте, ожидая при этом разных результатов от имитируемых методов? Я упускаю что-то основное, что заставило бы это работать так, как я ожидаю? Разделение утверждений на разные тесты, чтобы получить своего рода «TearDown» для сброса моих макетов?
Поскольку ->andReturn, похоже, использует «очередь» возвращаемых ответов, я получаю ожидаемые утверждения, просто передавая ему различные ожидаемые возвращаемые значения в том порядке, в котором я их ожидаю. Это похоже на очень «жестко запрограммированный» способ сделать это и подразумевает, что я должен знать точный порядок и количество возвратов, которые, как я ожидаю, даст любой тест для любого макета. Я бы предпочел иметь возможность в любой момент времени точно указать, что именно должен возвращать макет, изменяя его всякий раз, когда я считаю нужным...?
$mockQueryBuilder->shouldReceive('getResult')->andReturn($previousSuccessfulUpdate, null);
Подробнее здесь: [url]https://stackoverflow.com/questions/78511697/confusion-about-mock-reuse-in-phpunit[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия