Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
ErrorProcessorTest.php
Go to the documentation of this file.
1 <?php
9 
10 use \Magento\Framework\Webapi\ErrorProcessor;
11 
14 use Magento\Framework\Webapi\Exception as WebapiException;
16 
17 class ErrorProcessorTest extends \PHPUnit\Framework\TestCase
18 {
20  protected $_errorProcessor;
21 
23  protected $encoderMock;
24 
26  protected $_appStateMock;
27 
29  protected $_loggerMock;
30 
31  protected function setUp()
32  {
34  $this->encoderMock = $this->getMockBuilder(\Magento\Framework\Json\Encoder::class)
35  ->disableOriginalConstructor()
36  ->setMethods(['encode'])
37  ->getMock();
38 
39  $this->_appStateMock = $this->getMockBuilder(\Magento\Framework\App\State::class)
40  ->disableOriginalConstructor()
41  ->getMock();
42 
43  $this->_loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class)->getMock();
44 
45  $filesystemMock = $this->getMockBuilder(\Magento\Framework\Filesystem::class)
46  ->disableOriginalConstructor()
47  ->getMock();
48 
50  $this->_errorProcessor = new ErrorProcessor(
51  $this->encoderMock,
52  $this->_appStateMock,
53  $this->_loggerMock,
54  $filesystemMock
55  );
56 
57  parent::setUp();
58  }
59 
60  protected function tearDown()
61  {
62  unset($this->_errorProcessor);
63  unset($this->encoderMock);
64  unset($this->_appStateMock);
65  parent::tearDown();
66  }
67 
73  public function testRenderJson()
74  {
75  $_SERVER['HTTP_ACCEPT'] = 'json';
77  $this->encoderMock->expects(
78  $this->once()
79  )->method(
80  'encode'
81  )->will(
82  $this->returnCallback([$this, 'callbackJsonEncode'], $this->returnArgument(0))
83  );
85  ob_start();
86  $this->_errorProcessor->renderErrorMessage('Message');
88  $actualResult = ob_get_contents();
89  ob_end_clean();
90  $expectedResult = '{"messages":{"error":[{"code":500,"message":"Message"}]}}';
91  $this->assertEquals($expectedResult, $actualResult, 'Invalid rendering in JSON.');
92  }
93 
102  public function callbackJsonEncode($data)
103  {
104  return json_encode($data);
105  }
106 
112  {
113  $_SERVER['HTTP_ACCEPT'] = 'json';
115  $this->_appStateMock->expects($this->any())->method('getMode')->will($this->returnValue('developer'));
117  $this->encoderMock->expects(
118  $this->once()
119  )->method(
120  'encode'
121  )->will(
122  $this->returnCallback([$this, 'callbackJsonEncode'], $this->returnArgument(0))
123  );
124  ob_start();
125  $this->_errorProcessor->renderErrorMessage('Message', 'Message trace.', 401);
126  $actualResult = ob_get_contents();
127  ob_end_clean();
128  $expectedResult = '{"messages":{"error":[{"code":401,"message":"Message","trace":"Message trace."}]}}';
129  $this->assertEquals($expectedResult, $actualResult, 'Invalid rendering in JSON.');
130  }
131 
136  public function testRenderXml()
137  {
138  $_SERVER['HTTP_ACCEPT'] = 'xml';
140  ob_start();
141  $this->_errorProcessor->renderErrorMessage('Message');
143  $actualResult = ob_get_contents();
144  ob_end_clean();
145  $expectedResult = '<?xml version="1.0"?><error><messages><error><data_item><code>500</code>' .
146  '<message><![CDATA[Message]]></message></data_item></error></messages></error>';
147  $this->assertEquals($expectedResult, $actualResult, 'Invalid rendering in XML.');
148  }
149 
155  {
156  $_SERVER['HTTP_ACCEPT'] = 'xml';
158  $this->_appStateMock->expects($this->any())->method('getMode')->will($this->returnValue('developer'));
160  ob_start();
161  $this->_errorProcessor->renderErrorMessage('Message', 'Trace message.', 401);
163  $actualResult = ob_get_contents();
164  ob_end_clean();
165  $expectedResult = '<?xml version="1.0"?><error><messages><error><data_item><code>401</code><message>' .
166  '<![CDATA[Message]]></message><trace><![CDATA[Trace message.]]></trace></data_item></error>' .
167  '</messages></error>';
168  $this->assertEquals($expectedResult, $actualResult, 'Invalid rendering in XML with turned on developer mode.');
169  }
170 
175  public function testRenderDefaultFormat()
176  {
178  $_SERVER['HTTP_ACCEPT'] = 'undefined';
180  $this->encoderMock->expects($this->atLeastOnce())->method('encode');
181  $this->_errorProcessor->renderErrorMessage('Message');
182  }
183 
189  {
191  $this->_appStateMock->expects($this->once())->method('getMode')->will($this->returnValue('developer'));
193  $errorMessage = 'Error Message';
194  $logicalException = new \LogicException($errorMessage);
196  $maskedException = $this->_errorProcessor->maskException($logicalException);
197  $this->assertInstanceOf(\Magento\Framework\Webapi\Exception::class, $maskedException);
198  $this->assertEquals(
199  $errorMessage,
200  $maskedException->getMessage(),
201  'Exception was masked incorrectly in developer mode.'
202  );
203  }
204 
215  public function testMaskException($exception, $expectedHttpCode, $expectedMessage, $expectedDetails)
216  {
218  // TODO:MAGETWO-21077 $this->_loggerMock->expects($this->once())->method('critical');
219  $maskedException = $this->_errorProcessor->maskException($exception);
220  $this->assertMaskedException(
221  $maskedException,
222  $expectedHttpCode,
223  $expectedMessage,
224  $expectedDetails
225  );
226  }
227 
232  {
233  $thrownException = new \Exception('', 0);
234 
235  $this->_loggerMock->expects($this->once())
236  ->method('critical')
237  ->will(
238  $this->returnCallback(
239  function (\Exception $loggedException) use ($thrownException) {
240  $this->assertSame($thrownException, $loggedException->getPrevious());
241  }
242  )
243  );
244  $this->_errorProcessor->maskException($thrownException);
245  }
246 
251  {
252  return [
253  'NoSuchEntityException' => [
255  new Phrase(
256  'No such entity with %fieldName = %fieldValue, %field2Name = %field2Value',
257  [
258  'fieldName' => 'detail1',
259  'fieldValue' => 'value1',
260  'field2Name' => 'resource_id',
261  'field2Value' => 'resource10',
262  ]
263  )
264  ),
266  'No such entity with %fieldName = %fieldValue, %field2Name = %field2Value',
267  [
268  'fieldName' => 'detail1',
269  'fieldValue' => 'value1',
270  'field2Name' => 'resource_id',
271  'field2Value' => 'resource10',
272  ],
273  ],
274  'NoSuchEntityException (Empty message)' => [
275  new NoSuchEntityException(),
276  WebapiException::HTTP_NOT_FOUND,
277  'No such entity.',
278  [],
279  ],
280  'AuthorizationException' => [
282  new Phrase(
283  'Consumer %consumer_id is not authorized to access %resources',
284  ['consumer_id' => '3', 'resources' => '4']
285  )
286  ),
287  WebapiException::HTTP_UNAUTHORIZED,
288  'Consumer %consumer_id is not authorized to access %resources',
289  ['consumer_id' => '3', 'resources' => '4'],
290  ],
291  'Exception' => [
292  new \Exception('Non service exception', 5678),
293  WebapiException::HTTP_INTERNAL_ERROR,
294  'Internal Error. Details are available in Magento log file. Report ID:',
295  [],
296  ]
297  ];
298  }
299 
309  public function assertMaskedException(
310  $maskedException,
311  $expectedHttpCode,
312  $expectedMessage,
313  $expectedDetails
314  ) {
316  $expectedType = \Magento\Framework\Webapi\Exception::class;
317  $this->assertInstanceOf(
318  $expectedType,
319  $maskedException,
320  "Masked exception type is invalid: expected '{$expectedType}', given '" . get_class(
321  $maskedException
322  ) . "'."
323  );
325  $this->assertEquals(
326  $expectedHttpCode,
327  $maskedException->getHttpCode(),
328  "Masked exception HTTP code is invalid: expected '{$expectedHttpCode}', " .
329  "given '{$maskedException->getHttpCode()}'."
330  );
331  $this->assertContains(
332  $expectedMessage,
333  $maskedException->getMessage(),
334  "Masked exception message is invalid: expected '{$expectedMessage}', " .
335  "given '{$maskedException->getMessage()}'."
336  );
337  $this->assertEquals($expectedDetails, $maskedException->getDetails(), "Masked exception details are invalid.");
338  }
339 }
testMaskException($exception, $expectedHttpCode, $expectedMessage, $expectedDetails)