EmailNotificationTypeTest::getFrom()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace TonicHealthCheck\Test\Incident\Siren\NotificationType;
4
5
use PHPUnit_Framework_MockObject_MockObject;
6
use PHPUnit_Framework_TestCase;
7
use Swift_Mailer;
8
use Swift_Message;
9
use Swift_Transport;
10
use TonicHealthCheck\Incident\IncidentInterface;
11
use TonicHealthCheck\Incident\Siren\NotificationType\EmailNotificationType;
12
use TonicHealthCheck\Test\Incident\IncidentCreateTrait;
13
use TonicHealthCheck\Test\Incident\Subject\SubjectCreateTrait;
14
15
/**
16
 * Class EmailNotificationTypeTest.
17
 */
18
class EmailNotificationTypeTest extends PHPUnit_Framework_TestCase
19
{
20
    use SubjectCreateTrait;
21
    use IncidentCreateTrait;
22
    /**
23
     * @var string
24
     */
25
    private $from = '[email protected]';
26
27
    /**
28
     * @var string
29
     */
30
    private $fromName = 'Tester Test';
31
32
    /**
33
     * @var PHPUnit_Framework_MockObject_MockObject|Swift_Mailer;
34
     */
35
    private $mailer;
36
37
    /**
38
     * @var EmailNotificationType;
39
     */
40
    private $mailNType;
41
42
    /**
43
     * set base env for test EmailNotificationTypeTest.
44
     */
45
    public function setUp()
46
    {
47
        $this->setMailer(
48
            $this
49
            ->getMockBuilder(Swift_Mailer::class)
50
            ->disableOriginalConstructor()
51
            ->getMock()
52
        );
53
54
        $this->setMailNType(
55
            new EmailNotificationType(
56
                $this->getMailer(),
0 ignored issues
show
Bug introduced by
It seems like $this->getMailer() targeting TonicHealthCheck\Test\In...onTypeTest::getMailer() can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, TonicHealthCheck\Inciden...tionType::__construct() does only seem to accept object<Swift_Mailer>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
57
                $this->getFrom(),
58
                $this->getFromName()
59
            )
60
        );
61
    }
62
63
    /**
64
     * test email notify ok.
65
     */
66
    public function testNotify()
67
    {
68
        $incident = $this->createIncidentMock();
69
70
        $incident->expects($this->any())->method('getStatus')->willReturn(IncidentInterface::STATUS_OK + 1);
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in TonicHealthCheck\Incident\IncidentInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
71
72
        $subject = $this->createSubject('[email protected]', '* * * * *');
73
74
        $mailerTransport = $this->getMockBuilder(Swift_Transport::class)->getMock();
75
76
        $mailerTransport->expects($this->once())->method('stop');
77
78
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Swift_Mailer.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
79
            ->getMailer()
80
            ->expects($this->any())
81
            ->method('getTransport')
82
            ->willReturn($mailerTransport);
83
84
        $message = $this->createMessage($subject, $incident);
85
86
        $this
87
            ->getMailer()
88
            ->expects($this->any())
89
            ->method('send')
90
            ->with($this->callback($this->isMessageSame($message)));
91
92
        $this->getMailNType()->notify($subject, $incident);
0 ignored issues
show
Bug introduced by
It seems like $incident defined by $this->createIncidentMock() on line 68 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, TonicHealthCheck\Inciden...ificationType::notify() does only seem to accept object<TonicHealthCheck\...dent\IncidentInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
93
    }
94
95
    /**
96
     * @return string
97
     */
98
    protected function getFrom()
99
    {
100
        return $this->from;
101
    }
102
103
    /**
104
     * @return string
105
     */
106
    protected function getFromName()
107
    {
108
        return $this->fromName;
109
    }
110
111
    /**
112
     * @return PHPUnit_Framework_MockObject_MockObject|Swift_Mailer
113
     */
114
    protected function getMailer()
115
    {
116
        return $this->mailer;
117
    }
118
119
    /**
120
     * @param Swift_Mailer $mailer
121
     */
122
    protected function setMailer(Swift_Mailer $mailer)
123
    {
124
        $this->mailer = $mailer;
125
    }
126
127
    /**
128
     * @return EmailNotificationType
129
     */
130
    protected function getMailNType()
131
    {
132
        return $this->mailNType;
133
    }
134
135
    /**
136
     * @param EmailNotificationType $mailNType
137
     */
138
    protected function setMailNType(EmailNotificationType $mailNType)
139
    {
140
        $this->mailNType = $mailNType;
141
    }
142
143
    /**
144
     * @param Swift_Message $message
145
     *
146
     * @return \Closure
147
     */
148
    protected function isMessageSame(Swift_Message $message)
149
    {
150
        return function (Swift_Message $messageI) use ($message) {
151
            return $messageI->getFrom() == $message->getFrom()
152
            && $messageI->getTo() == $message->getTo()
153
            && $messageI->getSubject() == $message->getSubject()
154
            && $messageI->getBody() == $message->getBody();
155
        };
156
    }
157
158
    /**
159
     * @param $subject
160
     * @param $incident
161
     *
162
     * @return Swift_Message
163
     */
164
    protected function createMessage($subject, $incident)
165
    {
166
        $message = Swift_Message::newInstance()
167
            ->setTo($subject->getTarget())
168
            ->setFrom($this->getFrom(), $this->getFromName())
169
            ->setSubject(sprintf(EmailNotificationType::EMAIL_SUBJECT_T, $incident->getIdent()))
170
            ->setBody(sprintf(EmailNotificationType::EMAIL_BODY_T, $incident->getMessage(), $incident->getType()));
171
172
        return $message;
173
    }
174
}
175