Skip to content

Commit ad2d3c7

Browse files
committed
Implement unit tests and do some refactor to new QueueTransport and SendMailJob
1 parent 5646a4e commit ad2d3c7

File tree

4 files changed

+257
-15
lines changed

4 files changed

+257
-15
lines changed

src/Job/SendMailJob.php

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
namespace Cake\Queue\Job;
1818

19+
use Cake\Log\Log;
20+
use Cake\Mailer\AbstractTransport;
1921
use Cake\Queue\Queue\Processor;
2022

2123
/**
@@ -28,17 +30,50 @@ class SendMailJob implements JobInterface
2830
*/
2931
public function execute(Message $message): ?string
3032
{
31-
$transportClassName = $message->getArgument('transport');
32-
$config = $message->getArgument('config');
33-
$emailMessage = unserialize($message->getArgument('emailMessage'));
33+
$result = false;
3434
try {
35+
$transportClassName = $message->getArgument('transport');
36+
$config = $message->getArgument('config', []);
3537
/** @var \Cake\Mailer\AbstractTransport $transport */
36-
$transport = new $transportClassName($config);
38+
$transport = $this->getTransport($transportClassName, $config);
39+
40+
$emailMessage = unserialize($message->getArgument('emailMessage'));
3741
$result = $transport->send($emailMessage);
3842
} catch (\Exception $e) {
39-
return Processor::REJECT;
43+
Log::error(sprintf('An error has occurred processing message: %s', $e->getMessage()));
44+
} finally {
45+
if (!$result) {
46+
return Processor::REJECT;
47+
}
4048
}
4149

4250
return Processor::ACK;
4351
}
52+
53+
/**
54+
* Initialize transport
55+
*
56+
* @param string $transportClassName Transport class name
57+
* @param array $config Transport config
58+
* @return \Cake\Mailer\AbstractTransport
59+
* @throws \InvalidArgumentException if empty transport class name, class does not exist or send method is not defined for class
60+
*/
61+
protected function getTransport(string $transportClassName, array $config): AbstractTransport
62+
{
63+
if (
64+
empty($transportClassName) ||
65+
!class_exists($transportClassName) ||
66+
!method_exists($transportClassName, 'send')
67+
) {
68+
throw new \InvalidArgumentException(sprintf('Transport class name is not valid: %s', $transportClassName));
69+
}
70+
71+
$transport = new $transportClassName($config);
72+
73+
if (!($transport instanceof AbstractTransport)) {
74+
throw new \InvalidArgumentException('Provided class does not extend AbstractTransport.');
75+
}
76+
77+
return $transport;
78+
}
4479
}

src/Mailer/Transport/QueueTransport.php

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,9 @@ class QueueTransport extends \Cake\Mailer\AbstractTransport
3838
*/
3939
public function send(Message $message): array
4040
{
41-
QueueManager::push(
42-
[SendMailJob::class, 'execute'],
43-
[
44-
'transport' => $this->getConfig('transport'),
45-
'config' => $this->getConfig(),
46-
'emailMessage' => serialize($message),
47-
],
48-
$this->getConfig('options')
49-
);
41+
$data = $this->prepareData($message);
42+
$options = $this->getConfig('options');
43+
$this->enqueueJob($data, $options);
5044

5145
$headers = $message->getHeadersString(
5246
[
@@ -59,9 +53,40 @@ public function send(Message $message): array
5953
'returnPath',
6054
'cc',
6155
'bcc',
62-
],
56+
]
6357
);
6458

6559
return ['headers' => $headers, 'message' => 'Message has been enqueued'];
6660
}
61+
62+
/**
63+
* Add job to queue
64+
*
65+
* @param array $data Data to be sent to job
66+
* @param array $options Job options
67+
* @return void
68+
*/
69+
protected function enqueueJob(array $data, array $options): void
70+
{
71+
QueueManager::push(
72+
[SendMailJob::class, 'execute'],
73+
$data,
74+
$options
75+
);
76+
}
77+
78+
/**
79+
* Prepare data for job
80+
*
81+
* @param \Cake\Mailer\Message $message Email message
82+
* @return array
83+
*/
84+
protected function prepareData(Message $message): array
85+
{
86+
return [
87+
'transport' => $this->getConfig('transport'),
88+
'config' => $this->getConfig(),
89+
'emailMessage' => serialize($message),
90+
];
91+
}
6792
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
6+
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org/)
7+
*
8+
* Licensed under The MIT License
9+
* For full copyright and license information, please see the LICENSE.txt
10+
* Redistributions of files must retain the above copyright notice.
11+
*
12+
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org/)
13+
* @link https://cakephp.org CakePHP(tm) Project
14+
* @since 0.1.9
15+
* @license https://opensource.org/licenses/MIT MIT License
16+
*/
17+
namespace Cake\Queue\Test\TestCase\Job;
18+
19+
use Cake\Mailer\Transport\DebugTransport;
20+
use Cake\Queue\Job\Message;
21+
use Cake\Queue\Job\SendMailJob;
22+
use Cake\Queue\Queue\Processor;
23+
use Cake\TestSuite\TestCase;
24+
use Enqueue\Null\NullConnectionFactory;
25+
use Enqueue\Null\NullMessage;
26+
27+
class SendMailJobTest extends TestCase
28+
{
29+
/**
30+
* @var \Cake\Queue\Job\SendMailJob
31+
*/
32+
protected $job;
33+
34+
/**
35+
* @var \Cake\Mailer\Message
36+
*/
37+
protected $message;
38+
39+
/**
40+
* @inheritDoc
41+
*/
42+
public function setUp(): void
43+
{
44+
parent::setUp();
45+
46+
$this->job = new SendMailJob();
47+
$this->message = (new \Cake\Mailer\Message())
48+
->setFrom('[email protected]')
49+
->setTo('[email protected]')
50+
->setSubject('Sample Subject');
51+
}
52+
53+
/**
54+
* Test execute method
55+
*
56+
* @return void
57+
*/
58+
public function testExecute()
59+
{
60+
$message = $this->createMessage(DebugTransport::class, [], $this->message);
61+
$actual = $this->job->execute($message);
62+
$this->assertSame(Processor::ACK, $actual);
63+
}
64+
65+
/**
66+
* Test execute method with invalid transport
67+
*
68+
* @return void
69+
*/
70+
public function testExecuteInvalidTransport()
71+
{
72+
$message = $this->createMessage('WrongTransport', [], $this->message);
73+
$actual = $this->job->execute($message);
74+
$this->assertSame(Processor::REJECT, $actual);
75+
}
76+
77+
/**
78+
* Test execute method with unserializable message
79+
*
80+
* @return void
81+
*/
82+
public function testExecuteUnserializableMessage()
83+
{
84+
$message = $this->createMessage(DebugTransport::class, [], 'unserializable');
85+
$actual = $this->job->execute($message);
86+
$this->assertSame(Processor::REJECT, $actual);
87+
}
88+
89+
/**
90+
* Create a simple message for testing.
91+
*
92+
* @return \Cake\Queue\Job\Message
93+
*/
94+
protected function createMessage($transport, $config, $emailMessage): Message
95+
{
96+
$messageBody = [
97+
'class' => ['Queue\\Job\\SendMailJob', 'execute'],
98+
'data' => [
99+
'transport' => $transport,
100+
'config' => $config,
101+
'emailMessage' => serialize($emailMessage),
102+
103+
],
104+
];
105+
$connectionFactory = new NullConnectionFactory();
106+
$context = $connectionFactory->createContext();
107+
$originalMessage = new NullMessage(json_encode($messageBody));
108+
$message = new Message($originalMessage, $context);
109+
110+
return $message;
111+
}
112+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
6+
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org/)
7+
*
8+
* Licensed under The MIT License
9+
* For full copyright and license information, please see the LICENSE.txt
10+
* Redistributions of files must retain the above copyright notice.
11+
*
12+
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org/)
13+
* @link https://cakephp.org CakePHP(tm) Project
14+
* @since 0.1.9
15+
* @license https://opensource.org/licenses/MIT MIT License
16+
*/
17+
namespace Cake\Queue\Test\TestCase\Job;
18+
19+
use Cake\Queue\Mailer\Transport\QueueTransport;
20+
use Cake\TestSuite\TestCase;
21+
22+
class QueueTransportTest extends TestCase
23+
{
24+
/**
25+
* Test send
26+
*
27+
* @return void
28+
*/
29+
public function testSend()
30+
{
31+
$message = (new \Cake\Mailer\Message())
32+
->setFrom('[email protected]')
33+
->setTo('[email protected]')
34+
->setSubject('Sample Subject');
35+
36+
$transport = $this
37+
->getMockBuilder(QueueTransport::class)->onlyMethods(['enqueueJob'])
38+
->getMock();
39+
$expectedData = [
40+
'transport' => 'Cake\Mailer\Transport\MailTransport',
41+
'config' => [
42+
'options' => [],
43+
'transport' => 'Cake\Mailer\Transport\MailTransport',
44+
],
45+
'emailMessage' => serialize($message),
46+
];
47+
$expectedOptions = [];
48+
$transport->expects($this->once())
49+
->method('enqueueJob')
50+
->with($expectedData, $expectedOptions);
51+
$result = $transport->send($message);
52+
53+
$headers = $message->getHeadersString(
54+
[
55+
'from',
56+
'to',
57+
'subject',
58+
'sender',
59+
'replyTo',
60+
'readReceipt',
61+
'returnPath',
62+
'cc',
63+
'bcc',
64+
]
65+
);
66+
67+
$expected = ['headers' => $headers, 'message' => 'Message has been enqueued'];
68+
$this->assertEquals($expected, $result);
69+
}
70+
}

0 commit comments

Comments
 (0)