Добавлен Helper для AMQP, который собирает все поступающие сообщения и предоставляет методы для проверки созданных сообщений

Исправлен баг в форме ChangeUsernameForm
Исправлен баг с конфигурацией тестов, который не позволял правильно проводить проверки на существование\несуществование моделей
Добавлена поддержка передачи хоста Redis через env переменные в тестах
This commit is contained in:
ErickSkrauch 2016-12-04 19:56:49 +03:00
parent 363b25e6da
commit a8c7118e38
14 changed files with 188 additions and 20 deletions

View File

@ -28,15 +28,19 @@ class ChangeUsernameForm extends ApiForm {
];
}
public function change() {
public function change() : bool {
if (!$this->validate()) {
return false;
}
$transaction = Yii::$app->db->beginTransaction();
$account = $this->getAccount();
$oldNickname = $account->username;
if ($this->username === $account->username) {
return true;
}
$transaction = Yii::$app->db->beginTransaction();
try {
$oldNickname = $account->username;
$account->username = $this->username;
if (!$account->save()) {
throw new ErrorException('Cannot save account model with new username');

View File

@ -1,5 +1,6 @@
namespace: tests\codeception\api
actor: Tester
params: [env]
paths:
tests: .
log: _output

View File

@ -4,6 +4,7 @@ modules:
- Filesystem
- Yii2
- tests\codeception\common\_support\FixtureHelper
- tests\codeception\common\_support\amqp\Helper
- Redis
- Asserts
- REST:
@ -11,8 +12,8 @@ modules:
config:
Yii2:
configFile: '../config/api/functional.php'
cleanup: true
cleanup: false
Redis:
host: testredis
host: "%REDIS_HOST%"
port: 6379
database: 0

View File

@ -3,6 +3,8 @@ modules:
enabled:
- Yii2:
part: [orm, email, fixtures]
- tests\codeception\common\_support\amqp\Helper
config:
Yii2:
configFile: '../config/api/unit.php'
cleanup: false

View File

@ -25,9 +25,15 @@ class ConfirmEmailFormTest extends TestCase {
$this->assertInstanceOf(AccountSession::class, $result->getSession(), 'session was generated');
$activationExists = EmailActivation::find()->andWhere(['key' => $fixture['key']])->exists();
$this->assertFalse($activationExists, 'email activation key is not exist');
/** @var Account $user */
$user = Account::findOne($fixture['account_id']);
$this->assertEquals(Account::STATUS_ACTIVE, $user->status, 'user status changed to active');
/** @var Account $account */
$account = Account::findOne($fixture['account_id']);
$this->assertEquals(Account::STATUS_ACTIVE, $account->status, 'user status changed to active');
$message = $this->tester->grabLastSentAmqpMessage('events');
$body = json_decode($message->getBody(), true);
$this->assertEquals($account->id, $body['accountId']);
$this->assertEquals($account->username, $body['newUsername']);
$this->assertNull($body['oldUsername']);
}
private function createModel($key) {

View File

@ -18,9 +18,8 @@ class ConfirmNewEmailFormTest extends TestCase {
}
public function testChangeEmail() {
$accountId = $this->tester->grabFixture('accounts', 'account-with-change-email-finish-state')['id'];
/** @var Account $account */
$account = Account::findOne($accountId);
$account = Account::findOne($this->getAccountId());
$newEmailConfirmationFixture = $this->tester->grabFixture('emailActivations', 'newEmailConfirmation');
$model = new ConfirmNewEmailForm($account, [
'key' => $newEmailConfirmationFixture['key'],
@ -32,6 +31,23 @@ class ConfirmNewEmailFormTest extends TestCase {
]));
$data = unserialize($newEmailConfirmationFixture['_data']);
$this->assertEquals($data['newEmail'], $account->email);
$this->tester->canSeeAmqpMessageIsCreated('events');
}
public function testCreateTask() {
/** @var Account $account */
$account = Account::findOne($this->getAccountId());
$model = new ConfirmNewEmailForm($account);
$model->createTask(1, 'test1@ely.by', 'test@ely.by');
$message = $this->tester->grabLastSentAmqpMessage('events');
$body = json_decode($message->getBody(), true);
$this->assertEquals(1, $body['accountId']);
$this->assertEquals('test1@ely.by', $body['newEmail']);
$this->assertEquals('test@ely.by', $body['oldEmail']);
}
private function getAccountId() {
return $this->tester->grabFixture('accounts', 'account-with-change-email-finish-state')['id'];
}
}

View File

@ -35,6 +35,7 @@ class ChangeUsernameFormTest extends TestCase {
$this->assertTrue($model->change());
$this->assertEquals('my_new_nickname', Account::findOne($this->getAccountId())->username);
$this->assertInstanceOf(UsernameHistory::class, UsernameHistory::findOne(['username' => 'my_new_nickname']));
$this->tester->canSeeAmqpMessageIsCreated('events');
}
public function testChangeWithoutChange() {
@ -49,7 +50,8 @@ class ChangeUsernameFormTest extends TestCase {
'AND',
'username' => $username,
['>=', 'applied_in', $callTime],
]), 'no new UsernameHistory record, if we don\'t change nickname');
]), 'no new UsernameHistory record, if we don\'t change username');
$this->tester->cantSeeAmqpMessageIsCreated('events');
}
public function testChangeCase() {
@ -65,13 +67,17 @@ class ChangeUsernameFormTest extends TestCase {
UsernameHistory::findOne(['username' => $newUsername]),
'username should change, if we change case of some letters'
);
$this->tester->canSeeAmqpMessageIsCreated('events');
}
public function testCreateTask() {
$model = new ChangeUsernameForm();
$model->createEventTask('1', 'test1', 'test');
// TODO: у меня пока нет идей о том, чтобы это как-то успешно протестировать, увы
// но по крайней мере можно убедиться, что оно не падает где-то на этом шаге
$model->createEventTask(1, 'test1', 'test');
$message = $this->tester->grabLastSentAmqpMessage('events');
$body = json_decode($message->getBody(), true);
$this->assertEquals(1, $body['accountId']);
$this->assertEquals('test1', $body['newUsername']);
$this->assertEquals('test', $body['oldUsername']);
}
private function getAccountId() {

View File

@ -0,0 +1,106 @@
<?php
namespace tests\codeception\common\_support\amqp;
use Codeception\Exception\ModuleException;
use Codeception\Module;
use Codeception\Module\Yii2;
use Codeception\TestInterface;
class Helper extends Module {
public function _before(TestInterface $test) {
/** @var \Codeception\Lib\Connector\Yii2 $connector */
$connector = $this->getYii2()->client;
$app = $connector->getApplication();
$app->set('amqp', [
'class' => TestComponent::class,
]);
parent::_before($test);
}
/**
* Checks that message is created.
*
* ```php
* <?php
* // check that at least 1 message was created
* $I->seeAmqpMessageIsCreated();
*
* // check that only 3 messages were created
* $I->seeAmqpMessageIsCreated(3);
* ```
*
* @param string|null $exchange
* @param int|null $num
*/
public function seeAmqpMessageIsCreated($exchange = null, $num = null) {
if ($num === null) {
$this->assertNotEmpty($this->grabSentAmqpMessages($exchange), 'message were created');
return;
}
// TODO: заменить на assertCount() после релиза Codeception 2.2.7
// https://github.com/Codeception/Codeception/pull/3802
/** @noinspection PhpUnitTestsInspection */
$this->assertEquals(
$num,
count($this->grabSentAmqpMessages($exchange)),
'number of created messages is equal to ' . $num
);
}
/**
* Checks that no messages was created
*
* @param string|null $exchange
*/
public function dontSeeAmqpMessageIsCreated($exchange = null) {
$this->seeAmqpMessageIsCreated($exchange, 0);
}
/**
* Returns last sent message
*
* @param string|null $exchange
* @return \PhpAmqpLib\Message\AMQPMessage
*/
public function grabLastSentAmqpMessage($exchange = null) {
$this->seeAmqpMessageIsCreated();
$messages = $this->grabSentAmqpMessages($exchange);
return end($messages);
}
/**
* Returns array of all sent amqp messages.
* Each message is `\PhpAmqpLib\Message\AMQPMessage` instance.
* Useful to perform additional checks using `Asserts` module.
*
* @param string|null $exchange
* @return \PhpAmqpLib\Message\AMQPMessage[]
* @throws ModuleException
*/
public function grabSentAmqpMessages($exchange = null) {
$amqp = $this->grabComponent('amqp');
if (!$amqp instanceof TestComponent) {
throw new ModuleException($this, 'AMQP module is not mocked, can\'t test messages');
}
return $amqp->getSentMessages($exchange);
}
private function grabComponent(string $component) {
return $this->getYii2()->grabComponent($component);
}
private function getYii2() : Yii2 {
$yii2 = $this->getModule('Yii2');
if (!$yii2 instanceof Yii2) {
throw new ModuleException($this, 'Yii2 module must be configured');
}
return $yii2;
}
}

View File

@ -1,10 +1,16 @@
<?php
namespace tests\codeception\common\_support;
namespace tests\codeception\common\_support\amqp;
use common\components\RabbitMQ\Component;
use PhpAmqpLib\Connection\AbstractConnection;
class RabbitMQComponent extends Component {
class TestComponent extends Component {
private $sentMessages = [];
public function init() {
\yii\base\Component::init();
}
public function getConnection() {
/** @noinspection MagicMethodsValidityInspection */
@ -27,7 +33,26 @@ class RabbitMQComponent extends Component {
}
public function sendToExchange($exchangeName, $routingKey, $message, $exchangeArgs = [], $publishArgs = []) {
// ничего не делаем
$this->sentMessages[$exchangeName][] = $this->prepareMessage($message);
}
/**
* @param string|null $exchangeName
* @return \PhpAmqpLib\Message\AMQPMessage[]
*/
public function getSentMessages(string $exchangeName = null) : array {
if ($exchangeName !== null) {
return $this->sentMessages[$exchangeName] ?? [];
} else {
$messages = [];
foreach($this->sentMessages as $exchangeGroup) {
foreach ($exchangeGroup as $message) {
$messages[] = $message;
}
}
return $messages;
}
}
}

View File

@ -1,5 +1,6 @@
namespace: tests\codeception\common
actor: Tester
params: [env]
paths:
tests: .
log: _output

View File

@ -6,3 +6,4 @@ modules:
config:
Yii2:
configFile: '../config/common/unit.php'
cleanup: false

View File

@ -17,8 +17,5 @@ return [
// Для тестов нам не сильно важна безопасность, а вот время прохождения тестов значительно сокращается
'passwordHashCost' => 4,
],
'amqp' => [
'class' => tests\codeception\common\_support\RabbitMQComponent::class,
],
],
];

View File

@ -1,5 +1,6 @@
namespace: tests\codeception\console
actor: Tester
params: [env]
paths:
tests: .
log: _output

View File

@ -6,3 +6,4 @@ modules:
config:
Yii2:
configFile: '../config/console/unit.php'
cleanup: false